|
|
|
| Trang chủ .NET Việt Nam
>
Bài viết
>
Theo chủ đề
>
Nền tảng .NET/Mono | So sánh syntax c# and vb.net | Internet Internet or Some Document |
04:12' PM - Thứ hai, 23/06/2008 | | Sự khác biệt giữa VB.NET và C# được thể hiện ở ba phần chính: cú pháp,
các nguyên lý hướng đối tượng, và môi trường phát triển tích hợp Visual
Studio .NET. Sự khác biệt về cú pháp liên quan đến các câu lệnh và các
yếu tố ngôn ngữ. Sự khác biệt về hướng đối tượng thì khó thấy hơn, liên
quan đến bản hiện thực và tính năng giữa hai ngôn ngữ. Sự khác biệt về
môi trường phát triển tích hợp bao gồm những thiết lập biên dịch (là
những đặc tính được thiết lập thông qua IDE, có tác dụng khác nhau tùy
vào ngôn ngữ). Cũng có sự khác biệt thứ tư liên quan đến các tính năng
ngôn ngữ có trong ngôn ngữ này nhưng không có trong ngôn ngữ kia.
1. Sự khác biệt về cú pháp
Sự khác biệt về cú pháp là sự khác biệt thông thường nhất mà chúng ta
nghĩ đến khi so sánh hai ngôn ngữ. Sự khác biệt về cú pháp đề cập đến
sự khác biệt trong từ khóa và định dạng câu lệnh được sử dụng để thực
hiện các tác vụ giống nhau. Ví dụ: trong C#, câu lệnh được kết thúc
bằng dấu chấm phẩy; trong VB.NET, câu lệnh được kết thúc bằng dãy ký tự
chuyển dòng.
1.1 Phân biệt chữ hoa-thường
Một khác biệt chính giữa hai ngôn ngữ là C# có phân biệt chữ
hoa-thường, còn VB.NET thì không. Câu lệnh dưới đây đúng trong VB.NET
(tất cả đều viết thường):
Code: system.console.writeline("hello world") Trong C#, câu lệnh trên sẽ phát sinh lỗi. Cách viết đúng câu lệnh này trong C# như sau:
Code: System.Console.WriteLine("hello world"); Cả C# và VB.NET đều biên dịch thành một ngôn ngữ trung gian
(Intermediate Language—IL). Điều đáng nói là IL có phân biệt chữ
hoa-thường, nghĩa là VB.NET phải chuyển những dòng lệnh lúc biên dịch
sao cho trùng khớp dạng chữ của câu lệnh gốc ở mức IL. Một hiệu ứng lề của việc không phân biệt chữ hoa-thường là có những lúc
trình biên dịch không thể so trùng chính xác dạng chữ với khai báo gốc
của một hàm, dẫn đến kết quả không chính xác. Ví dụ:
Code: Class Account Overloads Function toString(ByVal Format As String) As String Return "My String with Format" End Function Overloads Overrides Function toString() As String Return "My String" End Function End Class Module App Sub Main() Dim acct As Object = New Account() System.Console.WriteLine(acct.ToString()) End Sub End Module Trong ví dụ trên, toString không chép đè phương thức ToString
trong lớp cơ sở, và phương thức toString không bao giờ được gọi. Ví dụ
này cho thấy sự phức tạp của việc có một ngôn ngữ không phân biệt chữ
hoa-thường trong khi tất cả đều phân biệt chữ hoa-thường.
Điều gì sẽ xảy ra nếu bạn thêm hai hàm công khai trong C# với tên giống
nhau nhưng khác dạng chữ hoa-thường? VB không thể sử dụng hàm này, và
báo rằng nó không thể phân giải hàm. Ví dụ, lớp Banking được viết trong
C# có hai phương thức MakeDeposit và makedeposit. Bạn có thể tham chiếu
DLL trong VB, và tạo một thể hiện của lớp Banking. Nhưng nếu bạn sử
dụng phương thức MakeDeposit hay makedeposit, trình biên dịch sẽ không
biết phải sử dụng phương thức nào. Để ngăn chặn điều này, bạn có thể
yêu cầu trình biên dịch kiểm tra sự chấp thuận của Common Language
Specification (CLS) bằng cách thêm dòng lệnh sau vào file
AssemblyInfo.cs của dự án C#:
Code: [assembly: System.CLSCompliant(true)] Nếu đang sử dụng trình biên dịch C#, bạn chỉ việc thêm dòng lệnh
này vào file mã nguồn sau các câu lệnh using. Sau khi thêm dòng lệnh
này, trình biên dịch C# sẽ thông báo lỗi nếu hai hàm công khai trong
lớp của bạn chỉ khác nhau ở dạng chữ.
1.2 Kết dòng Câu lệnh C# có thể được tách thành nhiều dòng với CRLF và được kết thúc
bằng một dấu chấm phẩy. Câu lệnh VB.NET chỉ có thể được tách bằng một
ký tự tiếp dòng và được kết thúc bằng CRLF. Đoạn mã sau minh họa cho
việc tách dòng trong C#:
C#.NET
Code: // Một dòng mã trong C#. string sName = sFirstName + sLastName; // Dấu chấm phẩy báo hiệu kết thúc câu lệnh. Bạn có thể tách dòng tại bất kì vị trí nào. Bạn có thể đặt mỗi từ
trên một dòng riêng, thậm chí có thể thêm chú thích ở cuối mỗi đoạn. Ví
dụ:
C#.NET
Code: string sName // biến = // toán tử sFirstName // tên + // toán tử sLastName; // Dấu chấm phẩy báo hiệu kết thúc câu lệnh. Bạn có thể thực hiện tương tự với các chuỗi trực kiện bằng cách đặt biểu tượng @ trước chuỗi:
C#.NET
Code: string sName = @"John Jacob Jingle Hymer Smith"; Tuy nhiên, đoạn mã trên cho kết quả là một chuỗi với ký tự xuống dòng được nhúng vào. Trong VB, để tách một dòng thành nhiều phần, bạn phải thêm một khoảng trắng và ký tự gạch dưới. Ví dụ:
VB.NET
Code: ' Một dòng trong VB. Dim sName As String = sFirstName + _ sLastName Giống như C#, bạn có thể tùy ý tách mỗi từ như ví dụ bên dưới.
Tuy nhiên, khác với C#, việc thêm chú thích cuối mỗi đoạn là không hợp
lệ.
Code: ' Một dòng trong VB. Dim _ sName _ As _ String _ = _ sFirstName _ + _ sLastName Khác với C#, việc tách các chuỗi trực kiện thành hai dòng là không hợp lệ.
1.3 Chú thích
C# phân biệt giữa chú thích dòng và chú thích khối. Chú thích dòng sử dụng hai dấu vạch xiên “//” như sau:
C#.NET
Code: // Đây là một chú thích. void MakeDeposit(int Amount) { int _Balance; // Số dư tài khoản. } Chú ý, trong đoạn mã trên, có một chú thích trước khai báo hàm và
một chú thích sau khai báo _Balance. Khi bạn sử dụng hai dấu vạch xiên,
tất cả văn bản sau hai dấu vạch này được xem như là một phần của chú
thích. Chú thích khối sử dụng một dấu vạch xiên theo sau là một dấu hoa thị
(/*) để bắt đầu khối, và kết thúc khối bằng một dấu hoa thị theo sau là
một dấu vạch xiên (*/). Ví dụ:
Code: /* Hàm: MakeDeposit Tầm vực: Public Mô tả: Tăng số dư tài khoản. Tác giả: Alibaba */ public void MakeDeposit(int Amount /*chú thích 1*/, int AmountAvail /*chú thích 2*/) {} Chú thích khối cho phép bạn viết một đoạn chú thích mà không cần
đặt hai dấu vạch xiên trên mỗi dòng, nhưng nó cũng cho phép bạn chèn
một chú thích bên trong một dòng mã. Chú thích khối có thể có các chú
thích được nhúng bên trong, ví dụ:
C#.NET
Code: /* // Đây là chú thích được nhúng vào. */ VB.NET chỉ có chú thích dòng. Các chú thích được tạo ra với câu
lệnh Rem hay với dấu nháy đơn (cách này thường được sử dụng hơn). Ví dụ:
VB.NET
Code: ' Đây là một chú thích. Rem Đây là một chú thích khác. Sub MakeDeposit(ByVal Amount As Integer) Dim _Balance As Integer ' Số dư tài khoản. End Sub Một hạn chế đối với các chú thích trong VB là bạn không thể chèn
một chú thích vào chính giữa một dòng lệnh như có thể thực hiện với chú
thích khối trong C#. 1.4 Khai báo và sử dụng không gian tên
Một không gian tên là một nhóm các lớp có cùng tiền tố. Ví dụ, nếu
không gian tên WidgetsUSA có hai lớp Checking và Savings thì tên đầy đủ
của hai lớp này sẽ là WidgetsUSA.Checking và WidgetsUSA.Savings.
Cả VB.NET và C# đều cho phép bạn định nghĩa không gian tên. Dưới đây là các ví dụ:
Code: namespace WidgetsUSA { namespace Banking { public class Checking {} public class Savings {} } } Code: Namespace WidgetsUSA Namespace Banking Class Checking End Class Class Savings End Class End Namespace End Namespace Tên đầy đủ của các lớp trong ví dụ này là
WidgetsUSA.Banking.Checking và WidgetsUSA.Banking.Savings. Việc khai
báo không gian tên tạo tên lớp duy nhất cho một nhóm cụ thể. Tuy nhiên,
nó trở nên cồng kềnh khi phải gõ tên lớp dài trong khai báo. Do đó, mỗi
ngôn ngữ cung cấp một câu lệnh cho phép lược bỏ phần tên không gian tên
và sử dụng tên lớp rút gọn trong khai báo. Trong C#, điều này được thực
hiện bằng câu lệnh using:
C#.NET
Code: using WidgetsUSA.Banking; class App { static void Main() { Checking check = new Checking(); } } Tương đương với using trong VB là câu lệnh Imports:
VB.NET
Code: Imports WidgetsUSA.Banking Class App Shared Sub Main() Dim check As Checking = New Checking() End Sub End Class Trong C# và VB.NET, bạn có thể gán một danh hiệu cho một không
gian tên. Điều này giúp giải quyết vấn đề nhập nhằng khi nhiều không
gian tên có tên lớp giống nhau. Xét hai lớp:
MyCompany.SharedCode.DatabaseClasses.Connection và
SomeOtherCompany.Modem.Connection. Giả sử một lập trình viên viết mã
lệnh sử dụng hay nhập không gian tên cho mỗi lớp như sau:
VB.NET
Code: Imports MyCompany.SharedCode.DatabaseClasses Imports SomeOtherCompany.Modem Class App Shared Sub Main() Dim cn As Connection End Sub End Class Trình biên dịch thông báo Connection trong các khai báo này là
nhập nhằng, nó có thể là của một trong hai không gian tên. Một giải
pháp là gán một danh hiệu cho một hoặc cả hai không gian tên như sau:
C#.NET
Code: using db=MyCompany.SharedCode.DatabaseClasses; using SomeOtherCompany.Modem; class App { static void Main() { db.Connection cn; } } VB.NET
Code: Imports db=MyCompany.SharedCode.DatabaseClasses Imports SomeOtherCompany.Modem Class App Shared Sub Main() Dim cn As db.Connection End Sub End Class Câu lệnh using thứ nhất trong C# và câu lệnh Imports thứ nhất
trong VB gán một danh hiệu (db) cho không gian tên
MyCompany.SharedCode.DatabaseClasses. Sau đó, bạn có thể sử dụng db
trong mã lệnh thay vì tên không gian tên. Điều này giúp đánh máy nhanh
hơn và cũng giải quyết vấn đề nhập nhằng. Dĩ nhiên, bạn có thể sử dụng
tên đầy đủ của không gian tên bất cứ khi nào bạn tham chiếu lớp để giải
quyết vấn đề nhập nhằng.
VB có một sự cải tiến so với C#. Nó cho phép bạn sử dụng Imports không chỉ với không gian tên mà còn với tên lớp. Ví dụ:
VB.NET
Code: Imports Microsoft.VisualBasic.ControlChars Module App Sub Main() Dim s As String = "Hello" + NewLine + "World" System.Console.WriteLine(s) End Sub End Module Câu lệnh Imports tham chiếu một không gian tên
(Microsoft.VisualBasic) và một lớp (ControlChars). Do đó, mã lệnh trong
Main có thể sử dụng các hằng trong lớp đó mà không phải sử dụng tên đầy
đủ của lớp. Một trong các hằng này là NewLine (biểu diễn ký tự xuống
dòng). 1.5 Khai báo biến
Trong C#, kiểu biến luôn đứng trước tên biến. Ví dụ:
C#.NET
Code: int x; decimal y; rectangle z; object obj; Trong VB, tên biến luôn đứng trước kiểu biến. Khai báo biến trong
VB bắt buộc phải có Dim hoặc các từ khóa: Public, Private, Friend,
Protected, Protected Friend. Khai báo sử dụng Dim thì mặc định là
Private. Mã lệnh trong VB như sau:
VB.NET
Code: Dim x As Integer Dim y As Decimal Dim z As Rectangle Dim obj As Object Cả hai ngôn ngữ đều cho phép bạn tạo một thể hiện của lớp bằng cách sử dụng từ khóa new. Dưới đây là ví dụ trong C#:
C#.NET
Code: class Account {} class App { static void Main() { // Ví dụ 1. Account acct = new Account(); // Ví dụ 2. Account acct2; acct2 = new Account(); } } Bạn có thể kết hợp khai báo đối tượng và thể hiện đối tượng trên cùng một dòng, hoặc có thể tách chúng ra. VB.NET có ba cách sử dụng toán tử new, được minh họa như sau:
VB.NET
Code: Class Account End Class Class App Shared Sub Main() ' Ví dụ 1. Dim acct As Account = new Account() ' Ví dụ 2. Dim acct2 As Account acct2 = new Account() ' Ví dụ 3. Dim acct3 As New Account End Sub End Class Cả ba ví dụ cùng tạo ra cùng IL. Ví dụ 3 tương tự với ví dụ 1, nó
khai báo một biến kiểu Account và tạo một đối tượng kiểu Account. Không
giống như các phiên bản trước của VB, ví dụ 3 tạo ngay một thể hiện của
đối tượng Account. Trong VB6 và các phiên bản trước, khi sử dụng As
New, đối tượng sẽ không được thể hiện hóa cho đến khi bạn sử dụng nó.
1.6 Khởi tạo biến
C# bắt buộc bạn phải khởi tạo các biến cục bộ một cách tường minh. Xét khai báo sau:
C#.NET
Code: class Account { int Balance; // trường public void MakeDeposit() { int tempBalance; // biến cục bộ // Lỗi biên dịch. Console.WriteLine(tempBalance); } } Lớp Account có trường Balance, phương thức MakeDeposit, và biến
cục bộ tempBalance. Trong C#, bạn không phải khởi tạo các trường trước
khi sử dụng chúng. Các trường sẽ được khởi tạo tự động là 0 nếu chúng
là kiểu số, và là null nếu chúng là kiểu tham chiếu. Tuy nhiên, trình
biên dịch C# sẽ thông báo lỗi nếu bạn sử dụng một biến cục bộ trước khi
gán giá trị cho nó. Trong VB.NET không có trường hợp này. VB.NET tự động khởi tạo tất cả
các biến cục bộ là 0 hay Nothing (hay tương đương, tùy thuộc vào lớp).
Xét mã lệnh VB sau:
VB.NET
Code: Class Account Dim Balance As Integer Sub MakeDeposit() Dim tempBalance As Integer ' Không có lỗi biên dịch. System.Console.WriteLine(tempBalance) End Sub End Class Trong ví dụ trên, cả Balance và tempBalance đều được khởi tạo là
0.Chỉ khi gặp vực thẳm, chúng ta mới tìm được kho báu của cuộc đời. 1.7 Khai báo thông số hàm
Có ba loại chỉ thị thông số: in (tham trị); in, out (tham chiếu); và
out. Khi một đối số được truyền bằng tham trị, những thay đổi trong hàm
được gọi không bị phản chiếu ngược trở lại caller; khi một đối số được
truyền bằng tham chiếu, chúng bị phản chiếu. Với các thông số tham
chiếu, bộ nhớ được định vị bởi caller, nhưng hàm có thể thay đổi giá
trị. Với các thông số out, bộ nhớ được định vị và giá trị được thiết
lập bởi hàm, caller chỉ nhận được giá trị. Cả C# và VB có thể sử dụng
cả ba loại thông số. Tuy nhiên, chúng hoạt động hơi khác giữa hai ngôn
ngữ. Xét hai ví dụ trong C# sau:
C#.NET
Code: void MakeDeposit(int x, ref int y, out int z) { x = 10; // Các thay đổi không bị phản chiếu đến caller. y = 10; // Các thay đổi bị phản chiếu đến caller. z = 10; // Bắt buộc. Các thay đổi bị phản chiếu đến caller. } void MakeDeposit(object obj1, ref object obj2, out object obj3) { obj1 = new object(); // Các thay đổi không bị phản chiếu đến caller. obj2 = new object(); // Các thay đổi không bị phản chiếu đến caller, // nhưng giờ đây caller có một tham chiếu đến một đối tượng khác. obj3 = new object(); // Bắt buộc. Hàm phải định vị đối tượng. } Ví dụ thứ nhất nhận các kiểu giá trị, ví dụ thứ hai nhận các kiểu
tham chiếu. Cả hai đều minh họa cách gửi một đối tượng bằng tham chiếu.
Đôi khi, lập trình viên hiểu sai rằng: khi truyền một đối tượng bằng
tham trị cho một hàm, hàm này không thể thay đổi các trường của đối
tượng đó. Xét mã lệnh sau:
C#.NET
Code: class person { public int Age; } class App { static void ChangeAge(person p1) { p1.Age=10; } } Trong ví dụ trên, p1 là thông số tham trị. “Tham trị” chỉ áp dụng
cho đối tượng mà biến trỏ tới; các trường của đối tượng lúc nào cũng có
thể bị thay đổi mà không phụ thuộc vào chỉ thị thông số đã được khai
báo. Đối với các đối tượng, việc truyền một đối tượng bằng tham trị chỉ
có nghĩa rằng: nếu hàm thiết lập biến-đại-diện-cho-đối-tượng thành một
đối tượng khác thì caller vẫn giữ tham chiếu đến đối tượng gốc khi hàm
này kết thúc. Nếu một đối tượng được truyền bằng tham chiếu và hàm
thiết lập biến-đại-diện-cho-đối-tượng thành một đối tượng mới thì
caller sẽ giữ tham chiếu đến đối tượng mới khi hàm này trả về.
Các thông số out thực ra là các thông số tham chiếu được đánh dấu bằng
một đặc tính đặc biệt để đơn giản hóa cách các thông số được truyền khi
truy xuất từ xa. Khi caller và đối tượng ở các máy khác nhau, càng ít
dữ liệu được truyền qua mạng càng tốt. Các thông số được truyền bằng
tham trị chỉ cần được truyền theo một chiều từ caller đến đối tượng.
Các thông số được truyền bằng tham chiếu cần được truyền từ caller đến
đối tượng, và ngược lại. Các thông số out chỉ cần được truyền từ đối
tượng đến caller.
VB hỗ trợ cả ba loại truyền thông số. Thông số tham trị được chỉ định
bằng cách lược bỏ từ khóa chỉ thị giống như trong C# hoặc bằng cách sử
dụng từ khóa ByVal:
VB.NET
Code: Sub MakeDeposit(ByVal num1 As Integer) End Sub Sub MakeDeposit(num1 As Integer) End Sub Thông số num1 được truyền bằng tham trị trong cả hai thủ tục. Bạn
phải sử dụng từ khóa ByRef để truyền một thông số tham chiếu như trong
ví dụ sau:
VB.NET
Code: Sub MakeDeposit(ByRef num2 As Integer) End Sub VB không có từ khóa cho các thông số out. Tuy nhiên, bạn có thể
sử dụng đặc tính <Out> để đại diện cho các thông số out. Ví dụ:
VB.NET
Code: Imports System.Runtime.InteropServices Sub MakeDeposit(<Out()> ByRef num1 As Integer) End Sub Mã lệnh này khai báo thông số num1 trong MakeDeposit là một thông
số out. Phiên bản C# đơn giản hơn, vì nó cung cấp một từ khóa để tự
động thêm đặc tính này. Trong C#, nếu bạn đánh dấu một thông số là out,
hàm phải gán giá trị cho thông số đó trước khi trả về, nếu không thì
trình biên dịch sẽ thông báo lỗi. Nhưng trong VB, bạn có thể áp dụng
đặc tính này cho một thông số ByRef hay cho một thông số ByVal. Trường
hợp sau là sai nhưng trình biên dịch không bắt lỗi.
1.8 Truyền thông số hàm
Trong C#, nếu một hàm chứa các thông số ref, bạn phải sử dụng từ khóa
ref trước mỗi đối số tham chiếu khi gọi hàm. Tương tự cho các thông số
out, từ khóa out phải xuất hiện trước bất cứ đối số nào ứng với một
thông số out. Cũng trong C#, không hợp lệ khi truyền một giá trị trực
kiện làm đối số cho thông số ref hay out (chẳng hạn, bạn không thể
truyền một số cho một thông số ref int). Bất cứ biến nào mà bạn truyền
làm đối số ref cũng phải được khởi tạo trước khi gọi phương thức. Đoạn
mã sau minh họa cho điều này:
C#.NET
Code: static void DoSomething(int x, ref int y, out int z) { z=45; } static void Main(string[] args) { int y=4; // Bạn phải khai báo và khởi tạo biến. int z; // Sử dụng ref và out trước đối số ref và out. DoSomething(5,ref y,out z); } Trong VB, bạn không phải sử dụng từ khóa trước các đối số của
phương thức, cho dù chúng là ByVal, ByRef, hay <Out> ByRef. Ví dụ
sau trình bày cách gọi hàm với các thông số ByRef trong VB.NET:
VB.NET
Code: Imports System.Runtime.InteropServices Module Module1 Sub DoSomething(ByVal x, ByRef y, <Out()> ByRef z) z = 45 End Sub Sub Main() Dim y As Integer Dim z As Integer ' y và z không cần được khởi tạo vì VB tự động khởi tạo các biến. DoSomething(5, y, z) ' Sẽ hợp lệ trong VB.NET khi truyền giá trị trực kiện cho ByRef. DoSomething(5, 10, 20) End Sub End Module Chú ý rằng không nhất thiết phải sử dụng ByRef trước các đối số
ByRef hoặc khởi tạo giá trị cho các biến đối số, bởi vì VB tự động khởi
tạo các biến cục bộ. VB cũng cho phép bạn truyền giá trị trực kiện cho
các thông số ByRef. 1.9 Thông số tùy chọn Trong VB, bạn chỉ định các thông số tùy chọn như sau: VB.NET Code: Sub MakeDeposit(Optional ByVal x As Integer=10) End Sub Optional có nghĩa là thông số có thể được lược bỏ. Nói cách khác,
bạn có thể gọi MakeDeposit(20) hay MakeDeposit(). Nếu thông số được
lược bỏ, giá trị mặc định (là 10 trong khai báo MakeDeposit ở trên) sẽ
được sử dụng. Các giá trị mặc định phải là các hằng bởi vì nếu caller
lược bỏ giá trị, trình biên dịch sẽ sử dụng giá trị mặc định. Do đó,
lúc thực thi, nó xuất hiện như thể caller không lược bỏ giá trị. Khả
năng lược bỏ các thông số khi gọi phương thức là đặc trưng của trình
biên dịch VB. Ví dụ, nếu bạn viết một lớp trong VB với một phương thức
có thông số tùy chọn, và sau đó sử dụng lớp này trong C#. Mã lệnh C#
không thể lược bỏ thông số đó trong lời gọi. Bạn có thể định nghĩa một thông số tùy chọn trong C# cũng giống như sử
dụng một đặc tính. Tuy nhiên, trong C#, thông số sẽ không là tùy chọn.
Nếu lớp C# được sử dụng trong chương trình VB, mã lệnh VB có thể lược
bỏ thông số tùy chọn. Trong trường hợp này, giá trị của nó sẽ là 0 hay
Nothing tùy thuộc vào kiểu biến, vì không có cách nào để chỉ định giá
trị mặc định thông qua các đặc tính trong C#. Đoạn mã sau trình bày
cách định nghĩa một phương thức với một thông số tùy chọn trong C#: C#.NET Code: using System.Runtime.InteropServices; public void MakeDeposit([Optional] int Amount) {} .10 Danh sách thông số
Trong C# và VB, bạn có thể khai báo một thông số là một danh sách thông
số (hay một mảng thông số)—một thông số có thể nhận một số lượng các
đối số biến, tất cả cùng kiểu; hoặc một mảng với một số lượng các phần
tử biến. Đoạn mã sau trình bày cách định nghĩa một mảng danh sách thông
số trong C# và cách gọi phương thức có chứa nó:
C#.NET
Code: // Định nghĩa (trong một lớp). public void MakeDeposit(params int[] Amount) {} // Gọi phương thức (trong một hàm). Account acct = new Account(); // Gọi phương thức với nhiều đối số. acct.MakeDeposit(50,100,20,30); // Gọi phương thức không có đối số. acct.MakeDeposit(); // Gọi phương thức với một mảng đối số. int[] Amounts = {50,100,20,30}; acct.MakeDeposit(Amounts); Đoạn mã trên gọi phương thức MakeDeposit ba lần: với 4 đối số,
không đối số nào, và với một mảng đối số. Với bộ thực thi .NET, việc
gọi MakeDeposit đơn giản là nhận một mảng số nguyên. Nếu bạn truyền
nhiều đối số, trình biên dịch phát sinh mã lệnh để tạo ra một mảng và
gán các giá trị cho nó, sau đó gọi MakeDeposit bằng cách truyền mảng
giá trị này.
Dưới đây là đoạn mã tương đương trong VB:
VB.NET
Code: ' Định nghĩa (trong một lớp). Sub MakeDeposit(ParamArray Amount As Integer()) End Sub ' Gọi phương thức (trong một hàm). Dim acct As New Account ' Gọi phương thức với nhiều đối số. acct.MakeDeposit(50,100,20,30) ' Gọi phương thức không có đối số. acct.MakeDeposit() ' Gọi phương thức với một mảng đối số. Dim amts As Integer() = {50,100,20,30} acct.MakeDeposit(amts) 1.11 Khai báo phương thức
Trong C#, tất cả phương thức đều là hàm. Một số hàm không trả về giá trị (void), ví dụ:
C#.NET
Code: public void MakeDeposit(int Amount) {} VB phân biệt hai loại phương thức: thủ tục (Sub) và hàm
(Function). Thủ tục là phương thức không trả về giá trị. Khi một chương
trình VB được biên dịch, thủ tục được chuyển thành hàm không trả về giá
trị, giống như C#. Đoạn mã sau trình bày một thủ tục và một hàm VB.NET:
VB.NET
Code: Sub MakeDeposit(ByVal Amount As Integer) End Sub Function IsOpen(ByVal AcctID As Integer) As Boolean End Function Chú ý rằng trong một hàm, bạn cần thêm As sau danh sách thông số, tiếp theo là kiểu trả về.
1.12 Trả về các thông số xuất
Cả C# và VB.NET đều có từ khóa return để trả về giá trị của một hàm và
thoát khỏi hàm. Đoạn mã sau minh họa cách sử dụng từ khóa này:
C#.NET
Code: public class Person { int m_Age = 10; // Sử dụng return với một thông số. public int GetAge() { return m_Age; } public void Speak() { if (m_Age < 1) return; // Làm gì đó khác tại đây. } } Hàm GetAge trả về nội dung của trường m_Age, hàm Speak không trả về giá trị. VB có một cách khác để trả về các thông số nhằm tương thích với các
phiên bản VB trước. Bạn chỉ việc thiết lập tên hàm thành giá trị trả về
(chú ý rằng: làm như thế sẽ không thoát khỏi hàm một cách tự động).
VB.NET
Code: Public Class Person Dim m_Age As Integer = 10 ' Sử dụng return với một thông số. Function GetAge() As Integer Return m_Age End Function Sub Speak() If m_Age < 1 Then Return ' Làm gì đó khác tại đây. End Sub 1.13 Khởi động chương trình
Tất cả các chương trình EXE đều bắt đầu với một thủ tục Main. VB.NET có
một tính năng cho phép dự án Windows Form chỉ định form khởi động thay
vì thủ tục Main. Tuy vậy, ngay cả trong trường hợp này, chương trình
cũng bắt đầu với một thủ tục Main (xem mục 3.3 để thấy cách làm việc).
Trong C#, Main (chữ M viết hoa) là một thủ tục tĩnh (static) của lớp.
Trong VB.NET, Main là một thủ tục chia sẻ (Shared) của lớp. Trong
VB.NET, Main cũng có thể nằm trong một Module. (Module là một lớp mà
tất cả các phương thức đều là Shared, xem mục B.1.17 để biết chi tiết).
Cả C# và VB đều cho phép bạn viết thủ tục Main theo ba cách khác nhau.
Ở dạng đơn giản nhất, bạn có thể viết thủ tục Main không có thông số.
Ví dụ:
C#.NET
Code:
class App { static void Main() { } }
VB.NET
Code:
Class App Shared Sub Main() End Sub End Class
Bạn cũng có thể viết thủ tục Main với một thông số là mảng kiểu
chuỗi. Mảng này chứa các đối số dòng lệnh được sử dụng lúc thực thi
chương trình. Ví dụ, người dùng có thể thực thi chương trình như sau:
program.exe param1 param2 /param3 "param4 param5"
Dưới đây là ví dụ cho cách viết thủ tục Main như thế:
C#.NET
Code:
class App { static void Main(string[] args) { foreach(string arg in args) { System.Console.WriteLine(arg); } } }
VB.NET
Code:
Class App Shared Sub Main(ByVal args As String()) Dim arg As String For Each arg In args System.Console.WriteLine(arg) Next End Sub End Class
Trong cách viết này, args là mảng chuỗi chứa các đối số dòng lệnh
của chương trình. Các đối số dòng lệnh không bao gồm tên chương trình,
chúng là các chuỗi theo sau tên chương trình. Mỗi đối số được phân cách
bằng một khoảng trắng. Để có một chuỗi chứa khoảng trắng làm đối số,
bạn phải thêm dấu ngoặc kép bao quanh nó. Đoạn mã trên xuất tất cả các
đối số dòng lệnh ra cửa sổ Console. Giả sử chúng ta sử dụng dòng lệnh
được mô tả ở trên, kết xuất như sau:
param1
param2
/param3
param4 param5
Bạn có thể có cách viết thứ ba cho thủ tục Main là một hàm trả về một
số nguyên. Cách này có thể lấy thông số là một mảng chuỗi hoặc không có
thông số. Số nguyên này là do lập trình viên định nghĩa. Do đó, bạn
phải định nghĩa các giá trị có nghĩa. Thông thường, trả về 0 là thành
công, khác 0 là có lỗi. Sau đây là ví dụ:
C#.NET
Code:
class App { static int Main() { return 0; } } VB.NET
Code: Chọn hết Class App Shared Function Main() As Integer Return 0 End Function End Class
Nhằm tạo tính tương thích lùi, VB cũng có hàm Command cho phép bạn lấy về các đối số dòng lệnh ở dạng một chuỗi đơn. Ví dụ:
VB.NET
Code:
Imports Microsoft.VisualBasic
Class App Shared Sub Main() Dim args As String = Command() System.Console.WriteLine(args) End Sub End Class
1.14 Thoát khỏi chương trình, phương thức, hay vòng lặp
VB.NET cung cấp nhiều câu lệnh để thoát khỏi một chương trình, phương
thức, hay vòng lặp. Để thoát khỏi chương trình, bạn sử dụng câu lệnh
End. Việc đặt End ở đâu trong mã lệnh sẽ làm cho chương trình kết thúc
tại đó. Ví dụ:
VB.NET
Code:
Module App Sub CheckSecurity(ByVal sID As String) If sID = "" Then End End If End Sub Sub Main() CheckSecurity("") End Sub End Module
C# không có phương thức tương đương để thoát khỏi chương trình.
Tuy nhiên, cả VB và C# đều có thể sử dụng phương thức
System.Environment.Exit. Dưới đây là ví dụ sử dụng phương thức Exit
trong C#:
C#.NET
Code:
class App { static void CheckSecurity(string sID) { if (sID == "") System.Environment.Exit(1); } static void Main(string[] Args) { CheckSecurity(""); } }
VB có một số câu lệnh để thoát khỏi phương thức, bao gồm Exit
Sub, Exit Function, và Exit Property. Một ví dụ với Exit Function như
sau:
VB.NET
Code:
Function MakeDeposit(ByVal Amount As Integer) As Integer If Amount < 0 Then Exit Function End If m_Balance += Amount Return m_Balance End Function
C# không có các phương thức tương đương. Tuy nhiên, điều này có
thể được thực hiện bằng câu lệnh return. Thực tế, đó là những gì VB
thực hiện bên trong.
VB.NET cũng có các phương thức để thoát khỏi vòng lặp, bao gồm Exit Do
(cho vòng lặp Do-While) và Exit For (cho vòng lặp For-Next). Ví dụ:
VB.NET
Class People
Dim Total As Integer
Sub FillAuditorium()
Dim iCount As Integer
For iCount = 1 To 500
Total += iCount
If Total > 250 Then
Exit For
End If
Next
System.Console.WriteLine(iCount)
End Sub
End Class
C# có câu lệnh tương đương là break. Câu lệnh break sử dụng cho vòng
lặp for, vòng lặp while và câu lệnh switch. Đoạn mã sau minh họa cách
sử dụng break để thoát khỏi một phương thức:
C#.NET
class People
{
int Total;
public void FillAuditorium()
{
int iCount;
for (iCount = 1; iCount <= 500; iCount++)
{
Total += iCount;
if (Total > 250)
break;
}
System.Console.WriteLine(iCount);
}
}
Một tính năng của C# nhưng không có trong VB.NET là câu lệnh continue.
Câu lệnh continue cho phép tiếp tục vòng lặp. Đoạn mã sau minh họa cách
sử dụng continue:
C#.NET
public class Person
{
string LastName;
int Age;
public static void SearchPeople(Person[] arr, int Age)
{
for (int i=0; i < arr.Length; i++)
{
if (arr[i].Age != Age)
continue;
System.Console.WriteLine(arr[i].LastName);
}
}
}
Trong đoạn mã trên, vòng lặp trong hàm SearchPeople duyệt qua một mảng
Person để tìm kiếm những người với tuổi cho trước. Câu lệnh if so sánh
tuổi của người hiện tại với tuổi mong muốn. Nếu không bằng nhau, mã
lệnh gọi continue để tiếp tục vòng lặp và trở về dòng lệnh đầu tiên
trong vòng lặp.
1.15 Tầm vực thành viên
Khi khai báo các thành viên của lớp như trường, phương thức, thuộc
tính, sự kiện, lớp lồng bên trong, v.v…, C# mặc định cho các thành viên
này là private, còn VB thì mặc định cho các thành viên này (trừ những
trường được khái báo bằng Dim) là public.
Bảng sau trình bày các từ khóa được sử dụng trong mỗi ngôn ngữ để chỉ tầm vực của một thành viên lớp:
Code: Chọn hết
C# VB.NET Chú thích
public Public Mặc định trong VB
private Private Mặc định trong C#
internal Friend
protected Protected
protected internal Protected Friend
1.16 Phương thức tĩnh và chia sẻ
Phương thức tĩnh là phương thức không được gắn vào một thể hiện cụ thể
của một lớp. Nói cách khác, bạn có thể gọi phương thức tĩnh mà không
cần tạo một thể hiện của lớp. Cũng vậy, trường tĩnh là trường không phụ
thuộc vào thể hiện của lớp.
Hạn chế của các phương thức tĩnh là chúng chỉ có thể gọi các phương
thức tĩnh khác, và chỉ có thể sử dụng các trường tĩnh. Chúng không thể
gọi các phương thức thể hiện hay sử dụng các trường thể hiện mà chưa
tạo ra thể hiện của lớp. Đoạn mã sau minh họa các trường và các phương
thức tĩnh:
C#.NET
class Account
{
public static int TotalAccounts;
int m_ID;
public static int GetNextAccountID()
{
return TotalAccounts;
}
public Account()
{
m_ID = GetNextAccountID();
TotalAccounts++;
}
}
Lớp Account có hai trường. Thứ nhất là TotalAccounts, được chỉ định là
tĩnh (tất cả các trường và hàm được chỉ định là public cho thuận tiện,
các trường tĩnh không cần là public). Thứ hai là m_ID, đây là một
trường thể hiện.
Đoạn mã trên cũng định nghĩa một phương thức tĩnh là GetNextAccountID.
Nếu xem xét mã lệnh, bạn sẽ thấy các hàm thể hiện (như là hàm khởi dựng
của lớp) có thể gọi các hàm tĩnh. Các hàm thể hiện cũng có thể truy
xuất các trường tĩnh. Tuy nhiên, sẽ không hợp lệ khi một hàm tĩnh gọi
các hàm thể hiện hay sử dụng các trường thể hiện. Nếu một hàm tĩnh cần
gọi một phương thức thể hiện, nó phải tạo một thể hiện trước, sau đó
gọi phương thức thể hiện.
Trong C#, để sử dụng các thành viên tĩnh từ bên ngoài lớp, bạn phải sử
dụng tên lớp. Ví dụ, nếu muốn truy xuất hàm GetNextAccountID hay trường
TotalAccounts, bạn thực hiện như sau:
C#.NET
class App
{
static void Main(string[] args)
{
int ID = Account.GetNextAccountID();
}
}
Sẽ không hợp lệ trong C# khi gọi một phương thức tĩnh hay sử dụng một
trường tĩnh thông qua một biến thể hiện. Đoạn mã sau sẽ có lỗi biên
dịch:
C#.NET
class App
{
static void Main(string[] args)
{
Account acct = new Account();
int ID = acct.GetNextAccountID(); // Lỗi.
}
}
VB cũng hỗ trợ các trường và các hàm tĩnh. VB sử dụng từ khóa Shared để
chỉ định các thành viên tĩnh. Dưới đây là đoạn mã VB tương đương:
VB.NET
Class Account
Shared TotalAccounts As Integer
Dim m_ID As Integer
Shared Function GetNextAccountID() As Integer
return TotalAccounts
End Function
Sub New()
m_ID = GetNextAccountID()
TotalAccounts+=1
End Sub
End Class
Cũng giống như trong C#, các hàm chia sẻ trong VB chỉ có thể gọi các
phương thức chia sẻ khác và sử dụng các trường chia sẻ. Tuy nhiên, các
hàm thể hiện có thể sử dụng bất kì các trường chia sẻ và gọi bất kì các
phương thức chia sẻ nào.
VB cho phép bạn gọi một phương thức chia sẻ hay sử dụng một trường chia
sẻ bằng cách sử dụng một biến trỏ tới một thể hiện của lớp, như ví dụ
sau:
VB.NET
Class App
Shared Sub Main()
' Hợp lệ trong cả hai ngôn ngữ.
Dim ID As Integer = Account.GetNextAccountID()
Dim Acct As New Account()
' Hợp lệ trong VB, không hợp lệ trong C#.
ID = Acct.GetNextAccountID()
End Sub
End Class
Trong ví dụ trên, sẽ hợp lệ khi gọi hàm GetNextAccountID bằng cách sử dụng tên lớp hay một thể hiện của lớp Account.
1.17 Lớp và đơn thể
VB.NET hỗ trợ các đơn thể mã lệnh, giúp lập trình viên viết các thư viện hàm toàn cục. Ví dụ:
VB.NET
Module App
Sub Main()
End Sub
End Module
Trình biên dịch VB chuyển một đơn thể thành một lớp, trong đó tất cả
thành viên được chỉ định là Shared (static trong C#). Lớp được tạo ra
là NotInheritable (sealed). Vì mỗi thành viên trong một đơn thể là
Shared, bạn không thể thêm các hàm khởi dựng thể hiện vào đơn thể, chỉ
được thêm một hàm khởi dựng chia sẻ.
Điều này không có trong C#, nhưng lập trình viên C# có thể mô phỏng một
đơn thể bằng cách viết một lớp sealed với tất cả các phương thức và
trường được chỉ định là static.
Thông thường, khi khai báo một phương thức chia sẻ trong một lớp, bạn
phải sử dụng tên lớp cộng với phương thức để gọi nó, ví dụ:
VB.NET
Class Math
Shared Function Add(Num1 As Integer, Num2 As Integer) As Integer
End Function
End Class
Module App
Sub Main()
System.Console.WriteLine(Math.Add(3,4))
End Sub
End Module
Để gọi phương thức Add, bạn phải viết Math.Add. Trong VB, nếu phương
thức là một phần của đơn thể, bạn có thể lược bỏ tên đơn thể:
VB.NET
Module Math
Function Add(Num1 As Integer, Num2 As Integer) As Integer
End Function
End Module
Module App
Sub Main()
System.Console.WriteLine(Add(3,4))
End Sub
End Module
Trong trường hợp này, bạn chỉ cần gọi phương thức Add. Điều này hoàn
toàn đúng miễn là trình biên dịch có thể báo phương thức Add nào được
gọi. Nếu bạn có hai đơn thể mà có cùng phương thức với cùng chữ ký, bạn
phải chỉ rõ tên đầy đủ bằng cách thêm tên đơn thể, như thể bạn đang gọi
phương thức chia sẻ từ một lớp.
Nếu đang viết một lớp trong C# để được sử dụng trong VB.NET, và muốn nó
giống một đơn thể, bạn có thể chỉ định mọi thành viên trong lớp là
static, sau đó tham chiếu đến assembly Microsoft.VisualBasic.dll và
thêm đặc tính StandardModule (thuộc không gian tên
Microsoft.VisualBasic.CompilerServices) vào lớp của bạn như sau:
C#.NET
[Microsoft.VisualBasic.CompilerServices.StandardMod ule]
public class Math
{
public static int Add(int num1, int num2)
{
return num1+num2;
}
}
Sau đó, một dự án VB có thể tham chiếu hàm Add một cách trực tiếp mà không cần tên lớp.
1.18 Câu lệnh if
Cả hai ngôn ngữ đều có câu lệnh điều kiện if. Tuy nhiên, cú pháp và ngữ
nghĩa thì khác nhau giữa hai ngôn ngữ. Trong C#, câu lệnh điều kiện
phải nằm trong dấu ngoặc đơn như sau:
C#.NET
if (x > 10)
DoSomething();
Chú ý, if là chữ thường, có dấu ngoặc đơn bao quanh câu lệnh điều kiện,
không cần có Then như trong VB. Trong ví dụ trên, câu lệnh if chỉ thực
hiện một tác vụ. Nếu có nhiều tác vụ để thực hiện, chúng được đặt trong
dấu ngoặc nhọn như sau:
C#.NET
if (x < 10)
{
DoTask1();
DoTask2();
}
Nếu muốn thêm một mệnh đề ngược lại, bạn phải sử dụng từ khóa else (chữ thường) như sau:
C#.NET
if (x < 10)
{
DoTask1();
DoTask2();
}
else
{
DoOtherTask1();
DoOtherTask2();
}
Nếu câu lệnh else của bạn cần kiểm tra một điều kiện khác, bạn thêm câu lệnh điều kiện if đó vào mệnh đề else như sau:
C#.NET
if (x < 10)
{
DoTask1();
DoTask2();
}
else if (x > 10)
{
DoOtherTask1();
DoOtherTask2();
}
else
{
DoNothing();
}
Trong VB, cú pháp có khác một chút. VB sử dụng If và cần có từ khóa Then như sau:
VB.NET
If x > 10 Then DoSomething()
Không cần thiết phải có dấu ngoặc đơn bao quanh câu lệnh điều kiện.
Giống như trong C#, câu lệnh If có thể thực hiện một hay nhiều tác vụ:
VB.NET
' Khi sử dụng "End If", "Then" là tùy chọn nhưng VS.NET thêm nó vào (mặc định).
If x < 10
DoTask1()
DoTask2()
End If
Thay vì bao quanh khối tác vụ bằng dấu ngoặc nhọn, VB sử dụng câu lệnh
End If ở cuối khối. Mệnh đề ngược lại có thể được chỉ định bằng từ khóa
Else:
VB.NET
If x < 10 Then
DoTask1()
DoTask2()
Else
DoOtherTask1()
DoOtherTask2()
End If
Trong trường hợp này, End If sau khối Else. Nếu mệnh đề ngược lại của
bạn cần có điều kiện If khác, bạn không thể viết như trong C#. Thay vào
đó, bạn phải sử dụng từ khóa ElseIf cho điều kiện thứ hai như sau:
VB.NET
If x < 10 Then
DoTask1()
DoTask2()
ElseIf x > 10 Then
DoOtherTask1()
DoOtherTask2()
Else
DoNothing()
End If
Khi nối các mệnh đề trong câu lệnh if, cả hai ngôn ngữ sử dụng các biểu
tượng khác nhau để đại diện cho các toán tử. Bảng sau trình bày các
toán tử được sử dụng trong mỗi ngôn ngữ:
VB.NET C# Toán tử
And && Và
Or || Hoặc
Not ! Phủ định
= == Bằng
Theo
Internet or Some Document Số lượt đọc:
413
-
Cập nhật lần cuối:
23/06/2008 04:12:25 PM | Bài đã đăng: Sử dụng Singleton Pattern trong C#18/06/2008 02:10' AMMẫu thiết kế Singletonlà
một trong những mẫu thông dụng và được sử dụng rộng rãi nhất trong kĩ
thuật lập trình. Về nguyên tắc, một Singleton là một lớp chỉ cho phép
một đối tượng tương ứng được tạo, và tất nhiên nó cũng phải có một
public member để những đối tượng khác có thể truy xuất instance Singletonnày Lợi ích của .NET Framework 06/06/2008 06:58' PM Mọi chuyện ... 'trên trời dưới đất' mà ta muốn thực hiện trên nền
Windows, tỷ như data access, windowing, nối mạng hay ngay cả mọi công
dụng đa dạng của Win32 API (Application Programming Interface) đều có
thể vận dụng dễ dàng qua kiểu mẫu đối tượng (objects) rất đơn giản
(simple object model). Làm việc với các file Tài Nguyên Resource 06/06/2008 01:22' PM Trong
một ứng dụng, có rất nhiều tài nguyên như: các file hình ảnh, âm nhạc,
văn bản... Vậy bạn có biết Làm thế nào để lưu tất cả những tài nguyên
đó vào cùng một file không? Và sẽ làm như thế nào? Bài viết này, mình
sẽ giới thiệu cho các bạn cách làm việc với các file tài nguyên
Resource: lưu trữ và đọc các thông tin đó.
Kiểu dữ liệu Hashtable 10/05/2008 01:47' AM
Bài viết giúp bạn hiểu về kiểu dữ liệu HastTable trong nền tảng .NET (ngôn ngữ C#). Tạo các ứng dụng .Net trên Linux và Mac OS X 25/04/2008 03:30' PM Bài
báo này được trích dẫn từ cuốn Windows Developer Power Tools của James
Avery và Jim Holmes, theo giấy phép của O’Reilly Media Inc. Visual Studio 2008 - New Features21/04/2008 12:46' AMVisual Studio 2008 code name "Orcas" Beta 2
has just hit the road and, since it is Beta 2, this means Visual Studio
2008 is feature complete and is ready for RTM. Below, we would find a
brief introduction of some of the new features introduced with VS 2008
and .NET 3.5 Beta 2. .net framwork3.0 21/04/2008 12:38' AM Cuối
tháng 5/2006, Microsoft công bố bản beta 2 của Windows Vista cùng một
số mô hình, công cụ giúp phát triển ứng dụng trên Windows như: .NET
Framework 3.0 (trước đây gọi là WinFX), Office 2007... Trong đó các
công cụ liên quan đến .NET Framework 3.0 được giới phát triển phần mềm
đặc biệt quan tâm. Theo kế hoạch, bản chính thức của .NET Framework 3.0
sẽ được công bố vào tháng 11/2006. .NET Framework 3.0 được Microsoft công bố là
thế hệ thứ 3 sau Win16 và Win32. |
|
|
|