Chương 29: So sánh C# với các ngôn ngữ khác
Tác giả: Sưu tầm
Khái quát
Chương này sẽ so sánh C# với các ngôn ngữ khác. C#, C++, và Java tất cả đều có chung một nguồn gốc và tương tự nhau so với những ngôn ngữ khác. Visual Basic không giống C# như những ngôn ngữ khác, nhưng nó vẫn có nhiều cú pháp giống.
Một phần trong chương này cũng thảo luận về phiên bản Visual C++ và Visual Basic trong .NET, vì chúng cũng có những cái khác so với trước.
Những khác biệt giữa C# và C/C++
C# sẽ quen thuộc với người lập trình C và C++, nhưng có một sự khác biệt lớn va một số khác biệt nhỏ khác. Sau đây là khái quát những điều đó.
Quản lý môi trường
C# chạy trên môi trường thời gian chạy .NET. Điều này không chỉ có nghĩa rằng có nhiều thứ mà không cần sự điều khiển của người lập trình, nó cũng cung cấp một khung làm việc mới. Tóm lại, có một số thứ đã được thay đổi.
- Việc xoá đối tượng là được thực hiện bằng trình gom rác sau khi một đối tượng không còn được sử dụng nữa. Hàm huỷ bỏ có thể được dùng để làm việc này, nhưng hàm huỷ bỏ C++ không làm theo cách này.
- Ngôn ngữ C# không sử dụng con trỏ. Nhưng cũng có những đoạn mã không an toàn, mà chúng hiếm khi được dùng. Thay vào đó ta sử dụng kiểu tham chiếu, và chúng là tương tự như tham chiếu trong C++ mà không có sự giới hạn của C++.
- Nguồn được dịch ra ngôn ngữ máy, mà nó chứa cả mã biên dịch (ngôn ngữ trung gian .NET, IL) và metadata mô tả mã biên dịch. Tất cả những ngôn ngữ trong .NET đòi hỏi metadata để xác định thông tin chung mà nó chứa trong tập tin C++ .h, và tập tin đính kèm do đó được vắng mặt.
- Việc gọi mã chuẩn đòi hỏi một mẫu nhiều công việc hơn.
- Không có một thư việc thời gian chạy C/C++. Những việc như thao tác chuỗi, nhập xuất tập tin, vào những công việc thường lệ khác có thể được làm với thời gian chạy .NET và được tìm thấy trong không gian tên System.
- Xử lý ngoại lệ được sử dụng thay vì việc đưa ra thông báo lỗi.
Các đối tượng .NET
Tất cả các đối tượng C# có một lớp cơ sở tận cùng là object, và chỉ có sự thừa kế đơn giữa các lớp, mặc dù có đa thực thi của giao diện.
Các đối tượng nhẹ ký, như kiểu dữ liệu, có thể được khai báo như cấu trúc (cũng được biết đến như kiểu giá trị), điều này có nghĩa là chúng được định vị trong stack thay vì trong heap.
Cấu trúc của C# và kiểu giá trị khác (bao gồm kiểu dữ liệu có sẵn) có thể được sử dụng trong những trường hợp mà đối tượng được đòi hỏi bằng cách đóng hộp chúng, đó là việc tự động sao chép giá trị vào một gói được xác định trong heap tương đương như đối tượng được xác định trong heap (cũng được biết đến như đối tượng tham chiếu). Điều này hợp nhất hệ thống kiểu, cho phép bất kỳ một biến nào đều được xem như một đối tượng, nhưng không quá lố khi sự hợp nhất là chưa cần thiết.
C# hỗ trợ thuộc tính và chỉ mục để phân tách mô hình người sử dụng của một đối tượng từ sự thực thi đối tượng, và nó hỗ trợ thẻ uỷ quyền và sự kiện để đóng gói con trỏ hàm và lời gọi trở lại.
C# cung cấp toán tử params để hỗ trợ tương tự như varags.
Câu lệnh trong C#
Câu lệnh trong C# là giống câu lệnh trong C++. Có một số khác biệt đáng chú ý:
- Toán tử new có nghĩa là “tồn tại một bản sao chép mới”. Đối tượng là được xác định trong heap nếu nó là một kiểu tham chiếu, và được xác định trong stack hay inline nếu nó là một kiểu giá trị.
- Tất cả các câu lệnh kiểm tra một điều kiện Boolean đòi hỏi một biến kiểu bool. Không có sự chuyển đổi kiểu tự động từ int ra bool, nên câu lệnh “if (i)” là sai.
- Câu lệnh switch không cho phép nhảy qua lại, để tránh lỗi. Switch cũng có thể được sử dụng cho những giá trị chuỗi.
- Foreach có thể được sử dụng để lặp trên object và collection.
- Checked và unchecked được sử dụng để điều khiển xem các phép số học và chuyển đổi kiểu là có bị tràn hay không.
- Bắt buộc một đối tượng phải được gán một giá trị trước khi sử dụng.
Đặc tính
Đặc tính là những chú giải được viết để chuyên chở những dữ liệu được khai báo từ người lập trình cho mã khác. Mã khác đó có thể là môi trường thực hiện, một trình thiết kế, một công cụ phân tích mã, hay một số công cụ quen thuộc khác. Thông tin đặc tính được trả ra thông qua một tiến trình được biết đến như sự ánh xạ.
Đặc tính được viết bên trong ngoặc vuông, và có thể được viết trong lớp, thành phần, tham số, và thành phần mã khác. Ví dụ:
[CodeReview(“1/1/199”, Comment=”Rockin”)]
class Test {}
Versioning
C# cho phép versioning tốt hơn C++. Bởi vì thời gian chạy xử lý bố trí thành phần, sự tương thích nhị phân là không phải một vấn đề. Thời gian chạy cung cấp các phiên bản gần nhau của thành phần nếu mong muốn, và ngữ nghĩa học đúng khi khung làm việc versioning, và ngôn ngữ C# cho phép người lập trình chỉ rõ chủ ý versioning.
Tổ chức mã
C# không có tập tin header; tất cả mã là được viết inline, và khi có hỗ trợ tiền xử lý cho mã điều khiện, không hỗ trợ macro. Sự hạn chế này làm cho trình biên dịch phân tích mã C# một cách dễ dàng và nhanh, và cũng tạo cho môi trường phát triển dễ dàng hiểu mã C#.
Ngoài ra, không có thứ tự phụ thuộc trong mã C#, và không có tuyên bố trước nào. Thứ tự của lớp trong tập tin nguồn là không quan trọng; lớp có thể được sắp xếp lại theo ý muốn.
Những đặc tính C# bỏ đi
Những đặc tính C++ sau đây không có trong C#:
- Đa thừa kế
- Hàm thành phần hoặc tham số hằng. Trường hằng được hỗ trợ.
- Biến toàn cục
- Typedef
- Chuyển đổi kiểu bằng hàm thiết lập
- Những giá trị mặc định trong thanh số hàm
Những khác biệt giữa C# và Java
C# và Java có cùng gốc, nên không ngạc nhiên khi có sự giống nhau giữa chúng. Tuy nhiên, có một số khác biệt rõ ràng giữa chúng. Sự khác nhau lớn nhất là C# là dựa trên nên tảng khung làm việc và thời gian chạy .NET, và Java là trên khung làm việc và thời gian chạy Java.
Kiểu dữ liệu
C# có nhiều kiểu dữ liệu cơ sở hơn Java. Bảng sau tóm tắt các kiểu của Java và kiểu C# tương tự:
Kiểu C# |
Kiểu Java |
Bình luận |
sbyte |
byte |
kiểu byte C# không dấu |
short |
short |
|
int |
int |
|
long |
long |
|
bool |
Boolean |
|
float |
float |
|
double |
double |
|
char |
char |
|
string |
string |
|
object |
object |
|
byte |
|
byte không dấu |
ushort |
|
short không dấu |
uint |
|
int không dấu |
ulong |
|
long không dấu |
decimal |
|
kiểu tiền tệ |
Trong Java, những kiểu có sẵn là trong một thế giới riêng biệt từ những kiểu đối tượng cơ sở. Đối với kiểu cơ sở để tham gia vào thế giới dựa trên đối tượng (ví dụ trong một tập hợp), chúng phải được đặt trong một thể hiện của một lớp được bọc, và lớp được bọc được đặt trong một tập hợp.
C# có cách khác để tiếp cận vấn đề này. Trong C#, kiểu cơ sở là được xác định trong stack như trong Java, nhưng chúng cũng được xem xét là dẫn xuất từ lớp cơ sở tận cùng, object. Điều này có nghĩa là kiểu cơ sở có thể có những hàm thành phần định nghĩa và gọi chúng. Mặt khác, ta thể viết như sau:
using System;
class Test {
public static void Main() {
Console. WriteLine(5.ToString());
}
}
Hằng 5 là kiểu int, và hàm ToString() là được định nghĩa trong kiểu int, nên trình biên dịch có thể phát sinh lời gọi đến nó và truyền số int đến hàm thành phần như thể nó là một đối tượng. Điều này vẫn làm việc tốt khi trình biên dịch biết nó đang xử lý một kiểu cơ sở, nhưng sẽ không làm việc khi một kiểu cơ sở cần được làm việc với một đối tượng được xác định trong heap trong một tập hợp. Bất cứ lúc nào một kiểu cơ sở là được sử dụng trong trường hợp khi một tham số của kiểu object là được đòi hỏi, trình biên dịch sẽ tự động đóng hộp kiểu cơ sở vào trong một người bọc được xác định trong heap. Đây là một ví dụ về đóng hộp:
Using System;
Class Test {
Public static void Main() {
Int v = 55;
Object o = v; // đóng hộp v thành o
Console.WriteLine(“Value is: {0}”,o);
Int v2 = (int)o; // mở hộp trở lại thành một giá trị int
}
}
Trong đoạn mã này, giá trị nguyên được đóng hộp thành một object và sau đó được in ra bằng hàm thành phần Console.WriteLine() như một đối số đối tượng. Việc định nghĩa biến đối tượng chỉ là minh hoạ; trong thực tế, v sẽ được chuyển đổi trực tiếp, và việc đóng hộp sẽ xảy ra tại vùng gọi. Giá trị nguyên bị đóng hộp có thể được lấy ra bằng phép toán cast, mà nó sẽ extract số int được đóng hộp.
Mở rộng hệ thống kiểu
Những kiểu C# cơ sở (ngoại trừ string và object) là cũng được biết đến như kiểu giá trị, bởi vì thực tế những biến có kiểu này chứa những giá trị. Những kiểu khác được biết đến như kiểu tham chiếu, bởi vì biến của chúng chứ những tham chiếu.
Trong C#, một lập trình viên có thể mở rộng hệ thống kiểu bằng cách thực thi một kiểu giá trị theo tuỳ chọn. Những kiểu này là được thực thi bằng cách sử dụng toán tử struct và đối sử tương tự như một kiểu giá trị có sẵn; chúng là được xác định trong stack, có thể có hàm thành phần được định nghĩa trong chúng, và được đóng hộp và tháo hộp khi cần thiết. Thực tế, những kiểu cơ sở C# tất cả đều được thực thi như kiểu giá trị, và chỉ có cú pháp khác nhau giữa kiểu có sẵn và kiểu người dùng định nghĩa là kiểu mà những kiểu có sẵn có thể được viết như hằng.
Để kiểu người dùng định nghĩa xử sự tự nhiên, cấu trúc C# có thể thực hiện chồng toán tử số học, và chuyển đổi kiểu ngầm và công khai giữa cấu trúc và các kiểu khác. C# cũng hỗ trợ chồng lớp. Một cấu trúc là được viết bằng cùng một cú pháp như lớp, ngoại trừ việc một cấu trúc không thể có một lớp cơ sở (mà là một lớp cơ sở ngầm định object), tuy nhiên nó có thể thực thi giao diện.
Lớp