Tải bản đầy đủ (.pdf) (102 trang)

C overview tieng viet

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.33 MB, 102 trang )

C# và .NET Framework

C# VÀ .NET FRAMEWORK - PHầN 1 - TRIếT LÝ CủA .NET
Như chúng ta đã biết cứ một vài năm, lập trình viên lại phải tìm hiểu
công nghệ mới của thời đại. Các ngôn ngữ (như C++, Visual Basic 6.0,
Java), framework (như MFC, ATL, STL), kiến trúc (như COM,
CORBA, EJB) rồi cũng sẽ bị lu mờ bởi những cái tốt hơn hay ít ra là
mới hơn. Và .NET flatform của Microsoft là một mảng trong bức tranh
của công nghệ phần mềm hiện nay.
Phần này sẽ trình bày về các khái niệm được dùng trong các phần sau,
như assembly, common intermediate language (CIL) và biên dịch
just-in-time (JIT). Ngoài ra để thấy được một số đặc tính nổi bật của
C# bạn cũng sẽ được làm quen với quan hệ giữa các khía cạnh của .NET
Framework, như common language runtime (CLR), Common Type
System (CTS), và Common Language Specification (CLS).
Phần này cũng trình bày tổng quan về các lớp thư viện của .NET (.NET
base class libraries) viết tắt là BSL hay FCL (Framework class
library). Cuối cùng, là phần tìm hiểu về language-agnostic và platformindependent của .NET flatform.
Các Câu Chuyện Từ Quá Khứ
Trước khi khám phá vũ trụ .NET, chúng tacũng nên biết một ít về những
platform trước đó của Microsoft, coi như là một "bài học về lịch sử" để
biết về cội nguồn và các giới hạn của chúng.
Cuộc Đời Của Lập Trình Viên C/Win32 API
Từ trước tới giờ, việc phát triển phần mềm cho hệ điều hành Windows
bao gồm việc sử dụng ngôn ngữ lập trình C kết hợp với giao diện lập
trình ứng dụng Windows - Windows application programming interface
(API). Các phần mềm được tạo ra thành công bằng việc sử dụng cách
tiếp cận mất thời gian kinh khủng này, nhưng một số lập trình viên


C# và .NET Framework



không đồng ý việc xây dựng phần mềm sử dụng thuần API là một việc
phức tạp.
Một vấn đề dễ thấy, C là một ngôn ngữ rất đơn giản. Lập trình viên C
bắt buộc phải quản lý bộ nhớ bằng tay, hơn nữa C là một ngôn ngữ cấu
trúc, và không hưởng được nhiều thuận lợi khi sử dụng tiếp cận hướng
đối tượng. Khi bạn kết hợp cả ngàn hàm toàn cục và các kiểu dữ liệu
được Win32 API định nghĩa thành một ngôn ngữ kinh khủng, và đó là cả
một kỳ quan nhỏ khi có nhiều ứng dụng vẫn tồn tại ngày nay.
Cuộc Đời Của Lập Trình Viên C++/MFC
Một cải tiến đáng kể của lập trình bằng C/Win32 API là sử dụng ngôn
ngữ C++. Theo nhiều cách, C++ được xem làm một lớp (layer) hướng
đối tượng nằm trên C. Do đó, mặc dù lập trình viên C++ có thuận lợi từ
OOP, nhưng vẫn còn bị bất lợi của ngôn ngữ C.
Dù phức tạp nhưng nhiều framework C++ vẫn tồn tại cho tới ngày nay.
Ví dụ như Microsoft Foundation Class (MFC) cung cấp một tập các lớp
C++ để dễ dàng xây dựng một ứng dụng Win32.
Cuộc Đời Của Lập Trình Viên Visual Basic 6.0
Ngôn ngữ Visual Basic 6.0 thông dụng vì khả năng xây dựng một giao
diện người dùng phức tạp, các thư viện, và khả năng truy dữ liệu logic
dễ hiểu. Thậm chí còn hơn cả MFC, VB6 dấu đi những thứ phức tạp của
Win32 API bằng việc sử dụng các hàm đặc biệt của VB.
Điểm yếu của VB là nó không thuần hướng đối tượng cộng thêm việc nó
không thể xây dựng một ứng dụng đa tiểu trình nếu bạn không lập trình
bằng các hàm Win32 API.
Cuộc Đời Của Lập Trình Viên Java/J2EE
Java đã là ngôn ngữ (gần như) hướng đối tượng hoàn toàn, nó có cú
pháp rất giống C++. Java cũng hỗ trợ platform independence. Java đã bỏ



C# và .NET Framework

bớt những cú pháp không cần thiết của C++ và cung cấp một lượng lớn
các lớp thư viện gọi là các “package”. Sử dụng các lớp này, lập trình
viên sẽ viết ra một ứng dụng “thuần 100% Java” gồm cả kết nối với cơ
sở dữ liệu, hỗ trợ message, web đầu cuối và giao diện người dùng thân
thiện.
Tuy nhiên một điểm yếu của Java là phải viết ứng dụng bằng Java từ đầu
đến cuối không thể tích hợp các ngôn ngữ khác. Ngoài ra Java cũng
không thích hợp khi viết các ứng dụng đồ họa nặng cần đến ngôn ngữ
cấp thấp (như C++) và cuối cùng Java chỉ cung cấp một khả năng làm
việc có giới hạn tới các non-Java API.
Cuộc Đời Của Lập Trình Viên COM
Component Object Model (COM) là framework phát triển ứng dụng của
Microsoft. COM là một kiến trúc với hiệu ứng “Nếu bạn xây dựng các
lớp theo luật của COM, bạn sẽ kết thúc bằng một khối mã nhị phân có
khả năng tái sử dụng”.
Vẻ đẹp của COM server là nó có thể được truy cập không phụ thuộc
ngôn ngữ. Do đó lập trình viên C++ xây dụng lớp COM có thể dùng cho
VB6. Lập trình viên Delphi có thể sử dụng các lớp COM được xây dựng
bằng C. Tuy nhiên khả năng độc lập ngôn ngữ của COM cũng có giới
hạn. Ví dụ như không thể kế thừa một lớp COM có sẵn mà chỉ có thể tạo
lớp với quan hệ “has-a” mà thôi.
Một thuận lợi khác của COM là việc trong suốt ngôn ngữ khi sử dụng.
Sử dụng application identifier (AppIDs), stub, proxy và COM runtime
environment giúp lập trình viên có thể bỏ qua việc tương tác với các
cổng, RPC và các chi tiết cấp thấp khác.
Mặc dùng COM được xem là một mô hình đối tượng khá thành công,
nhưng nó cũng cực kỳ phức tạp.



C# và .NET Framework

Cuộc Đời Của Lập Trình Viên Windows DNA
Qua nhiều năm, Microsoft dần dần thêm vào các tính năng với Internet
trong các hệ điều hành và sản phẩm. Mà việc sử dụng COM-based
Windows Distributed interNet Appication Architecture (DNA) lại khá
phức tạp.
Tính phức tạp này đơn giản là do Windows DNA đòi hỏi sử dụng quá
nhiều ngôn ngữ và công nghệ (ASP, HTML, XML, JavaScript,
VBScript, và COM (+) cũng như các API truy cập dữ liệu như ADO).
Và mỗi ngôn ngữ hay công nghệ lại có các kiểu dữ liệu riêng. Như “int”
trong JavaScript không giống với “Integer” trong VB6.

Giải Pháp .NET
Đã quá nhiều cho bài học lịch sử. Bây giờ đến .NET Framework, là
một tiếp cận làm cho đời dễ thở hơn. Giải pháp được .NET đưa ra là
“Thay đổi mọi thứ”. Như bạn sẽ thấy .NET Framework là một mô hình
hoàn toàn mới cho việc xây dựng các hệ thống trên Windows cũng
nhưng các nền khác như Mac OS X hay các phiên bản của Unix/Linux.
Sau đây là một số đặc tính cốt lõi của .NET:
Khả năng tương thích đầy đủ với code có sẵn: Đây tất nhiên là
một điều tốt. COM binary có sẵn có thể hoạt động chung với .NET
binary. Cũng như, Platform Invocation Services (Pinvoke) cho
phép bạn gọi hàm từ thư viện C (bao gồm cả các API của hệ điều
hành) từ code .NET.
Tích hợp ngôn ngữ đầy đủ và tổng quát: Không giống như
COM, .NET hỗ trợ việc kế thừa cross-language (tạm hiểu là xuyên
ngôn ngữ), bắt exception cross-language, và debug cross-language.
Một common runtime engine chia sẻ cho mọi ngôn ngữ dùng

.NET: Một khía cạnh của engine này là một tập các kiểu định
nghĩa sẵn mà mọi ngôn ngữ dùng .NET đề “hiểu”.


C# và .NET Framework

Một thư viện các lớp nền tảng (base class library): Thư viện này
cung cấp các đóng gói từ các hàm API phức tạp và đưa lên cho các
ngôn ngữ dùng .NET một mô hình đối tượng thich hợp.
Không còn hệ thống COM: Không còn IClassFactory,
IUnknown, IDispatch, IDL code và các kiểu VARIANT kinh
khủng (như BSTR, SAFEARRAY,…) trong code .NET.
Một mô hình triển khai thật sự dơn giản: Với .NET, không cần
phải đăng ký binary unit vào registry của hệ thống. Hơn nữa .NET
cho phép nhiều phiên bản của cùng *.dll tồn tại hài hòa trên một
máy.
Giới Thiệu .NET Flatform (CLR, CTS, và CLS)
Bây giờ bắt đầu xem qua ba chìa khóa đã làm nên tất cả: CLR, CTS và
CLS. Từ quan điểm của lập trình viên, .NET có thể hiểu như là một môi
trường runtime mới và một thư viện các lớp nền tảng. Layer runtime là
một thuộc tính được giao cho common language runtime hay CLR.
Chức năng chính của CLR là xác định, tải lên, và quản lý các kiểu .NET
của bạn. CLR còn lo cho các chi tiết cấp thấp khác như việc quản lý bộ
nhớ và thực hiện kiểm tra bảo mật.
Một khối khác của .NET flatform là Common Type System, hay CTS.
CTS mô tả tất cả các kiểu dữ liệu có thể có và hỗ trợ khởi tạo lúc
runtime, đặc tả các thực thể có thể tương tác với nhau ra sao, và mô tả
chi tiết chúng được thể hiện như thế nào trong định dạng metadata của
.NET.
Có thể một ngôn ngữ dùng .NET nào đó không hỗ trợ các tính năng do

CTS định nghĩa. Nên mới có Common Language Specification (CLS),
là một đặc tả quan hệ dùng định nghĩa một tập con của các kiểu phổ
thông và việc khởi tạo mà tất cả các ngôn ngữ .NET có thể dùng. Do đó
nếu bạn dùng các kiểu do .NET cung cấp, bạn có thể yên tâm là các
ngôn ngữ dùng .NET sẽ hiểu. Ngược lại khi bạn dùng một kiểu dữ liệu
hoặc cách khởi tạo khác ngoài CLS, thì không bảo đảm tất các ngôn ngữ
.NET khác có thể hiểu code của bạn.


C# và .NET Framework

Vai Trò của các Base Class Library
Ngoài CLR và CTS/CLS, .NET platform còn cung cấp một thư viện
base class hỗ trợ cho tất cả các ngôn ngữ lập trình .NET. Thư viện này
định nghĩa ra rất nhiều lớp để làm dễ dàng hơn khi thực hiện truy xuất
CSDL, XML, lập trình bảo mật,…

Mối quan hệ giữa CLR, CTS, CLS và Base Class Library

Kiến trúc .NET Framework


C# và .NET Framework

C# Có Gì Mới
Microsoft đã tạo ra ngôn ngữ lập trình mới, C# (đánh vần là “see sharp”
đừng đọc là “C thăng” nghe bưởi lắm), để phục vụ cho nền .NET mới
này. Thoạt nhìn thì thấy C# khá giống với Java, nhưng nói C# phỏng
theo cú pháp của Java thì không đúng. Vì cả C# và Java đều dựa trên cú
pháp của C++. Java chỉ là phiên bản rõ ràng hơn của C++, và C# lại là

bản rõ ràng hơn của Java - cuối cùng, chúng cũng chung trong một gia
đình ngôn ngữ lập trình.
Ngôn ngữ C# có một số đặc tính sau (một số trong đây cũng có trong
các ngôn ngữ dùng .NET):
Không còn con trỏ!
Cơ chế tự động dọn dẹp bộ nhớ nên C# không cần từ khóa delete.
Cú pháp chuẩn cho việc xây dựng enumeration, structure và các
thuộc tính của class.
Khả năng thực hiện overload operator dễ dàng hơn nhiều.
Khả năng xây dựng các kiểu generic (từ phiên bản C# 2005), sử
dụng một cú pháp giống với C++ template.
Hỗ trợ hoàn toàn lập trình interface.
Hỗ trợ hoàn toàn kỹ thuật lập trình hướng khía cạnh (aspectoriented programming - AOP) thông qua attribute. Cho phép bạn
gán thêm các đặc tính cho kiểu và thành phần của nó.
Ngoài ra code không được chạy bằng .NET runtime được gọi là
“unmanaged code”
Các Ngôn Ngữ Lập Trình Dùng .NET Khác
Chúng ta đã biết rằng, C# không phải chỉ là ngôn ngữ duy nhất dùng
trên nền .NET. Khi lần đầu tiên .NET xuất hiện tại Microsoft
Professional Developers Conference (PDC) năm 2000, nhiều hãng đã
cho biết không khó để xây dựng các trình biên dịch cho các ngôn ngữ
khác. Ngoài các ngôn ngữ được Visual Studio 2005 hỗ trợ (C#, J#, VB
.NET, Managed Extensions for C++, và JScript), còn các trình biên dịch


C# và .NET Framework

khác cho Smalltalk, COBOL, và Pascal.
Bảng dưới đây là một số ngôn ngữ dùng .NET.


Ngoài ra bạn có thể tham khảo một danh sách đầy đủ hơn ở địa chỉ
/>Sống trong Thế Giới Đa Ngôn Ngữ
Với các lập trình viên lần đầu tìm hiểu .NET, đã đặt ra khá nhiều câu
hỏi. Một trong những câu hỏi được dặt ra nhiều nhất là “Nếu các ngôn
ngữ .NET đều được biên dịch thành „managed code‟, thì tại sao lại phải
cần nhiều trình biên dịch thay vì chỉ một?” Cũng có nhiều cách để trả lời
câu hỏi này. Đầu tiên, các lập trình viên như chúng ta có người thích cái
này người thích cái kia, người thì thích gọn gàng với các dấu mở đóng
ngoặc và chấm phẩy, có người lại khoái ngôn ngữ giống văn viết hơn
(như VB.NET).
Nên, nếu Microsoft chỉ xây dựng một phiên bản ngôn ngữ “chính thức”
cho .NET từ ngôn ngữ BASIC thì bạn có thích không? Hay được xây
dựng từ cú pháp của Fortran? Chắc người ta bỏ đi hết
. Vì .NET
runtime không quan tâm đến ngôn ngữ đang được sử dụng để tạo ra
managed code là gì, nên các lập trình viên có thể chia sẻ các assembly
(*.dll và *.exe) với nhau nhưng vẫn viết theo ngôn ngữ mình thích.


C# và .NET Framework

Một thực tế khác là, nếu bạn đã viết .NET theo một ngôn ngữ nào đó rồi,
thì bạn cũng dễ dàng quán triệt một ngôn ngữ dùng .NET khác.
Tổng Quan .NET Assembly
Không cần quan tâm ngôn ngữ .NET bạn chọn là gì, phải chú ý là mặc
dùng các binary của .NET có đuôi giống như COM server hay
unmanaged Win32 binary (*.dll hay *.exe), nhưng bên trong chúng hoàn
toàn khác biệt. Quan trọng nhất là bên trong .NET binary không chứa
bất kỳ lệnh cho một nền cụ thể nào cả, thay vào đó là intermediate
language (IL) và kiểu metadata.


Ghi chú: Trong quá trình phát triển .NET “IL” được gọi là Microsoft
intermediate language (MSIL).Tuy nhiên khi phát hành .NET, thuật ngữ
này đã được chuyển thành common intermediate language (CIL). Do đó
khi đọc về .NET, nếu bạn gặp IL, MSIL hay CIL thì đó chỉ là một.
Nhưng trong bài viết này mình sẽ dùng “CIL”
Khi một *.dll hay *.exe được tạo ra bằng một trình biên dịch .NET,
module kết quả sẽ được đưa vào một assembly.
Như đã đề cập ở trên, assembly chứa code CIL, nó cũng giống khái
niệm bytecode bên Java. Code này chưa được biên dịch thành mã máy ở


C# và .NET Framework

một nền cụ thể nào cả cho đến khi nó thật sự cần thiết. “Thật sự cần
thiết” ở đây muốn ám chỉ đến việc các lệnh CIL được .NET runtime sử
dụng.
Ngoài các lệnh CIL, assembly còn chứa metadata mô tả chi tiết đặc
tính của mọi “kiểu” trong binary. Ví dụ, bạn có một lớp tên là SportsCar,
kiểu metadata sẽ mô tả về base class của SportCar, những interface nào
mà SportCar implement (nếu có), cũng như là thông tin đầy đủ về các
thành phần được hỗ trợ bởi kiểu SportCar.
Và cuối cùng, ngoài CIL và kiểu metadata, các assembly còn được mô tả
bằng việc sử dụng metadata, được gọi với thuật ngữ chính thức là
manifest. Manifest chứa các thông tin về phiên bản hiện tại của
assembly, thông tin về văn hóa (được dùng cho localizing string và các
tài nguyên hình ảnh), và một danh sách các tham chiếu đến assembly
khác được yêu cầu sử dụng để thực thi.
Single-file và Multifile Assembly
Trong nhiều trường hợp, chỉ có một quan hệ một-một đơn giản giữa

.NET assembly và binary file (*.dll hay *.exe). Do đó nếu bạn xây dựng
một .NET *.dll, thì assembly và binary chỉ hiểu là một. Tương tự, nếu
bạn tạo một ứng dụng, thì *.exe ám chỉ là một assembly. Nhưng thật ra
thì không hoàn toàn chính xác, nhưng chúng ta sẽ tìm hiểu sau. Nếu một
assembly được tạo ra từ một module *.dll hay *.exe, thì bạn có có
một single-file assembly. Single-file assembly chứa trong đó tất cả các
CIL cần thiết, metadata và manifest có liên quan trong một package duy
nhất.
Ngược lại, multifile assembly, được tạo ra từ nhiều .NET binary, mỗi
cái trong đó được gọi là một module. Khi tạo ra một đa assembly, một
trong các module đó (được gọi là primary module) phải chứa assembly
manifest (và các lệnh CIL và metadata cho các kiểu dữ liệu). Những
module còn lại sẽ chứa các manifest, CIL và metadata ở cấp module.


C# và .NET Framework

Thế tại sao chúng ta nên dùng multifile assembly? Rất đơn giản, khi bạn
chia nhỏ một assembly thành nhiều module, bạn sẽ có lựa chọn linh hoạt
hơn khi triển khai ứng dụng. Ví dụ, nếu người dùng reference tới một
remote assembly và cần phải được download xuống máy của người đó,
bộ runtime chỉ phải tải các module cần thiết, thay vì phải tải hết tất cả
bao gồm cả những thứ không cần thiết nếu chúng ta dùng single-file
assembly.
Vai Trò của Common Intermediate Language
Bạn đã biết nhiều hơn về .NET assembly, bây giờ chúng ta sẽ đi sâu hơn
về vai trò của common intermediate language (CIL). CIL là một ngôn
ngữ nằm trên tập các mã máy của các nền khác nhau. Không cần quan
tâm ngôn ngữ viết .NET là gì, trình biên dịch đó cũng tạo ra các lệnh
CIL. Ví dụ chúng ta có một đoạn code C# như sau, lớp Calc với phương

thức Add:
Code:
// The C# calculator.
public class Calc
{
public int Add(int x, int y)
{ return x + y; }
}
Thì khi biên dịch sẽ tạo ra đoạn CIL như sau (bạn có thể dùng công cụ
ildasm.exe để xem, cách sử dụng sẽ được trình bày trong phần sau):
Code:
.method public hidebysig instance int32 Add(int32 x, int32 y) cil
managed
{
// Code size 8 (0x8)
.maxstack 2
.locals init ([0] int32 CS$1$0000)


C# và .NET Framework

IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: add
IL_0003: stloc.0
IL_0004: br.s IL_0006
IL_0006: ldloc.0
IL_0007: ret
} // end of method Calc::Add
Và bây giờ, chúng ta sẽ có một đoạn code tương tự nhưng được viết

bằng VB.NET
Code:
Class Calc
Public Function Add(ByVal x As Integer, ByVal y As Integer) As
Integer
Return x + y
End Function
End Class
Và bạn cũng sẽ có một đoạn CIL tương tự (dĩ nhiên là được biên dịch
bằng VB.NET) cho phương thức Add():
Code:
.method public hidebysig instance int32 Add(int32 x, int32 y) cil
managed
{
// Code size 8 (0x8)
.maxstack 2
.locals init ([0] int32 CS$1$0000)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: add
IL_0003: stloc.0


C# và .NET Framework

IL_0004: br.s IL_0006
IL_0006: ldloc.0
IL_0007: ret
} // end of method Calc::Add
Download source code

Lợi Ích Của CIL
Đến thời điểm này, có thể bạn sẽ tự hỏi, có lợi như thế nào khi biên dịch
mã nguồn sang CIL, thay vì làm trực tiếp ra mã máy. Một thuận lợi là
tích hợp ngôn ngữ. Như bạn đã thấy, mỗi trình biên dịch ngôn ngữ dùng
.NET đều sẽ tạo ra các lệnh CIL gần như giống nhau. Do đó, tất cả các
ngôn ngữ đều có thể tương tác được với nhau.
Hơn nữa, thật ra có một chuẩn quốc tế cho ngôn ngữ C# và các phiên
bản khác của nền .NET chạy trên các hệ điều hành không phải trên
Windows. Nhưng ngược lại với Java, .NET cho phép bạn chọn ngôn ngữ
khi xây dựng ứng dụng.
Biên dịch CIL thành Mã Máy cho một Platform cụ thể
Assembly chỉ chứa các lệnh CIL thay vì mã máy trên một nền (platform)
nào đó, nên CIL code phải được biên dịch runtime (on the fly) trước khi
được sử dụng. Trình biên dịch biên dịch CIL code thành mã máy cho
CPU hiểu được gọi là just-in-time (JIT) compiler hay đôi khi còn được
gọi với cái tên gần gũi hơn là Jitter. .NET runtime environment sẽ dùng
JIT compiler tối ưu cho mỗi platform nó chạy trên.
Ví dụ nếu bạn xây dựng ứng dụng .NET trên di động, Jitter sẽ được
trang bị để chạy trên một môi trường có bộ nhớ thấp. Ngược lại nếu bạn
triển khai ứng dụng trên hệ thống Server, Jitter sẽ được tối ưu để sử
dụng cho môi trường có bộ nhớ lớn.
Hơn nữa, các Jitter biên dịch CIL code thành mã máy thích hợp và được


C# và .NET Framework

nhớ tạm trên vùng nhớ thích hợp tùy mỗi hệ điều hành. Với cách này thì
nếu bạn gọi một hàm tên là PrintDocument(), CIL code sẽ được biên
dịch và để tạm tại một vùng nhớ nào đó để sử dụng lại. Nên lần sau khi
bạn gọi PrintDocument(), sẽ không cần biên dịch lại CIL nữa.

Chức Năng của .NET Metadata
Ngoài các lện CIL, .NET assembly còn chứa cả một metadata đầy đủ,
hoàn chỉnh và chính xác mô tả tất cả các kiểu (class, structure,
enumeration,…) được định nghĩa trong binary, cũng như tất cả các thành
phần trong mỗi kiểu (property, method, event,…). Assembly đã là một
khối thực thể tự mô tả hoàn toàn nên .NET binary không cần đăng ký
vào registry hệ thống là vì vậy.
Để mô tả cấu trúc của .NET metadata. Chúng ta sẽ xem xét metadata
được tạo ra cho phương thức Add() trong lớp Calc.
Code:
TypeDef #2 (02000003)
------------------------------------------------------TypDefName: CalculatorExample.Calc (02000003)
Flags : [Public] [AutoLayout] [Class]
[AnsiClass] [BeforeFieldInit] (00100001)
Extends : 01000001 [TypeRef] System.Object
Method #1 (06000003)
------------------------------------------------------MethodName: Add (06000003)
Flags : [Public] [HideBySig] [ReuseSlot] (00000086)
RVA : 0x00002090
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: I4
2 Arguments
Argument #1: I4
Argument #2: I4


C# và .NET Framework


2 Parameters
(1) ParamToken : (08000001) Name : x flags: [none] (00000000)
(2) ParamToken : (08000002) Name : y flags: [none] (00000000)
Metadata được dùng bởi rất nhiều khía cạnh khác nhau của .NET
runtime environment, cũng như bởi các công cụ phát triển khác nhau. Ví
dụ, tính năng Intellisense của Visual Studio 2005 được thực hiện bằng
cách đọc metadata của assembly lúc design time. Metadata còn được
dùng bởi các tiện ích browse object, các công cụ debug, và trình biên
dịch của C#. Và metadata là xương sống của nhiều kỹ thuật khác nhau
trong .NET gồm có remoting, reflection, late binding, XML web service
và object serialization.
Chức Năng của Assembly Manifest
Bạn phải nhớ rằng .NET assembly cũng chứa metadata mô tả cho chính
nó (và được gọi bằng thuật ngữ manifest). Manifest ghi lại thông tin của
tất cả các essembly bên ngoài được assembly hiện tại sử dụng để thao
tác với chúng được chính xác, như version của assembly, thông tin
copyright, và nhiều thứ khác. Giống như metadata, chuyện tạo ra
manifest của assembly là việc của trình biên dịch. Đây là một số chi tiết
có liên quan của CSharpCalculator.exe manifest:
Code:
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
.ver 2:0:0:0
}
.assembly CSharpCalculator
{
.hash algorithm 0x00008004
.ver 0:0:0:0
}

.module CSharpCalculator.exe


C# và .NET Framework

.imagebase 0x00400000
.subsystem 0x00000003
.file alignment 512
.corflags 0x00000001
Tóm lại manifest chứa đựng thông tin của các assembly bên ngoài mà
CsharpCalculator dùng (bằng khai báo .assembly extern) cũng như các
thông tin khác của chính nó (version, tên module,…).
Tìm Hiểu Common Type System
Một assembly có thể chứa đủ loại “kiểu” (type). Trong .NET, “type” chỉ
đơn giản là một thuật ngữ chung sử dụng để ám chỉ bộ {class, structure,
interface, enumeration, delegate}. Khi bạn xây dựng một ứng dụng trên
một ngôn ngữ .NET, bạn sẽ thường xuyên tiếp xúc với các loại này. Ví
dụ, assembly của bạn định nghĩa một class cài đặt (implement) từ nhiều
interface. Trong interface đó có phương thức có tham số là kiểu
enumeration số và trả về một kiểu structure.
Nhớ là Common Type System (CTS) là một đặc tả để cho biết các kiểu
phải được định nghĩa như thế nào để CLR làm việc. Sau đây chúng ta sẽ
lướt qua các kiểu này.
CTS Class Type
Tất cả ngôn ngữ .NET đều hỗ trợ, và được gọi là kiểu class, thành phần
cốt lõi của lập trình hướng đối tượng (OOP). Một class có thể có nhiều
thành viên (như property, method, và event) và dữ liệu (field). Trong C#,
class được khai báo bằng từ khóa class.
Code:
// A C# class type.

public class Calc
{
public int Add(int x, int y)
{ return x + y; }


C# và .NET Framework

}
Một số tính chất của class:
Class có “ẩn” được không? – Class ẩn (Sealed class) không
giống với base class hoặc các class khác.
Class cài đặt được nhiều interface không? – Một interface là
một tập hợp của các thành viên ảo cung cấp một hợp đồng giữa
object và cái sử dụng object. CTS cho phép một class có thể cài đặt
bao nhiêu interface cũng được.
Class là ảo hay thật? – Lớp ảo (abstract class) không thể tạo trực
tiếp nhưng cung cấp các thuộc tính để lớp kết thừa định nghĩa. Lớp
thật (concrete class) được tạo trực tiếp.
Khả năng truy xuất của class là gì? – Mỗi class được cấu hình
với một thuộc tính truy xuất. Đơn giản là định nghĩa một class có
thể cho assembly bên ngoài dùng, hoặc chỉ trong nội bộ một
assembly dùng.

CTS Structure Type
Khái niệm của một structure cũng được đặc tả trong CTS. Nếu bạn biết
C, bạn sẽ hài lòng khi kiểu do người dùng định nghĩa này (user-defined
type – UDT) vẫn còn tồn tại ở .NET (mặc dù ở bên dưới có đôi chút
khác biệt). Structure đơn giản được xem như là một class đơn giản hoạt
động bằng giá trị. C# tạo structure bằng từ khóa struct.

Code:
// A C# structure type.
struct Point
{
// Structures can contain fields.
public int xPos, yPos;
// Structures can contain parameterized constructors.


C# và .NET Framework

public Point(int x, int y)
{ xPos = x; yPos = y;}
// Structures may define methods.
public void Display()
{
Console.WriteLine("({0}, {1}", xPos, yPos);
}
}

CTS Enumeration Type
Enumeraion là một kiểu cấu trúc cho phép bận nhóm các cặp tên và giá
trị. Ví dụ, giả sử bạn đang viết một trò chơi cho phép người chơi chọn
một trong 3 loại (Wizard, Fighter hay Thief). Thay vì phải quản lý chúng
theo kiểu giá trị thông thường, chúng ta có thể xây dựng một kiểu
enumeration với từ khóa là enum.
Code:
// A C# enumeration type.
public enum CharacterType
{

Wizard = 100,
Fighter = 200,
Thief = 300
}
Mặc định, mỗi item sẽ lưu trữ một giá trị 32-bit integer; tuy nhiên, nó
cũng có thể thay đổi kiểu dữ liệu nếu cần (trong trường hợp bộ nhớ thấp
như của Pocket PC). Ngoài ra, các kiểu enum đều được mặc định kế
thừa từ System.Enum. Trong các bài viết sau mình sẽ đề cập đến vấn đề
này.
CTS Delegate Type


C# và .NET Framework

Delegate là một kiểu-an-toàn của C# tương ứng với con trỏ hàm bên C.
Khác biệt chính là .NET delegate là một lớp được kế thừa từ
System.MulticaseDelegate, thay vì chỉ là một con trỏ tới một địa chỉ.
Trong C#, các delegate được khai báo với từ khóa delegate.
Code:
// Đây là một C# delegate type có thể 'trỏ tới' bất kỳ phương thức nào
// trả về một số nguyên và đầu vào là hai số nguyên.
public delegate int BinaryOp(int x, int y);
Delegate được dùng khi bạn muốn đưa ra một cách cho một thực thể gọi
một thực thể khác và là nền tảng của kiến trúc sự kiện trong .NET. Các
bài viết sau sẽ đề cập đến vấn đề này sâu hơn.
CTS Type Member
Bạn đã xem qua các loại được đặc tả bởi CTS, và thấy rằng hầu hết các
kiểu đều có các thành viên. Chính xác gọi là type member được ràng
buộc bởi {constructor, finalizer, static constructor, nested type, operator,
method, property, indexer, field, read only field, constant, event}.

CTS còn định nghĩa ra những phần khác có liên quan đến member này.
Ví dụ, mỗi member còn có khả năng truy xuất (public, private,
protected,…). Một số member được khai báo abstract để có khả năng đa
hình. Và hầu hết member đều có thể là static (dùng theo cấp class) hoặc
intance (dùng theo cấp object).
Các Kiểu Dữ Liệu CTS Cơ Bản
Các kiểu này được định nghĩa trong mscorlib.dll.


C# và .NET Framework

Tìm Hiểu Common Language Specification
Như bạn đã biết, mỗi một ngôn ngữ đều có một cú pháp riêng cho mình.
Ví dụ C# sử dụng dấu + làm toán tử ghép chuỗi, trong khi đó VB.NET
thì lại dùng dấu &. Thậm chí khi hai ngôn ngữ thể hiện cùng một ít,
code của chúng cũng khá khác nhau. Ví dụ một phương thức không có
giá trị trả về của VB.NET và C#:
Code:
' VB .NET method returning nothing.
Public Sub MyMethod()
' Some code...
End Sub
// C# method returning nothing.
public void MyMethod()
{
// Some code...
}


C# và .NET Framework


Như bạn đã thấy, một ngôn ngữ .NET có thể có hoặc không việc hỗ trợ
giá trị không dấu, hay có hoặc không việc hỗ trợ con trỏ. Theo vấn đề
này thì nên có một tiêu chuẩn để mọi ngôn ngữ .NET phải tuân theo.
Common Language Specification (CLS) chính là tập các luật mô tả đến
từng chi tiết nhỏ và đầy đủ nhất về các tính năng của .NET compiler
phải hỗ trợ để tạo code cho CLR. CLS có thể được xem là một phần con
trong toàn bộ tính năng của CTS.
Tìm Hiểu Common Language Runtime
Thuật ngữ runtime có thể được hiểu như một tập hợp của các service bên
ngoài được yêu cầu thực thi một phần code đã biên dịch. Ví dụ, khi lập
trình viên sử dụng Microsoft Foundation Classes (MFC) để tạo ra một
ứng dụng mới, họ sẽ cần đến thư việc MFC runtime (mfc42.dll). Các
ngôn ngữ thông dụng khác cũng đều có một bộ runtime tương ứng. Lập
trình viên VB6 sử dụng module msvbvm60.dll. Lập trình viên Java sử
dụng Java Virtual Machine (JVM)…
.NET platform cũng đưa ra một hệ thống runtime khác. Mấu chốt chỗ
khác nhau giữa .NET runtime và các bộ runtime khác, như đã trình bày
ở trên là nó cũng cấp một lớp runtime tổng quát cho tất cả các ngôn ngữ
và các platform sử dụng .NET.
Bộ runtime này chính là thư viện mscoree.dll (Common Object Runtime
Execution Engine). Khi một assembly được tham chiếu để sử dụng,
mscoree.dll được tự động tải lên và tải assembly cần dùng vào bộ nhớ.
Bộ runtime engine này chịu trách nhiệm cho toàn bộ các tác vụ. Đầu tiên
và trước nhất, engine này sẽ điều khiển việc xác định vị trí của assembly
và tìm các type được yêu cầu trong binary bằng cách đọc metadata chứa
trong đó. Sau đó CLR sẽ phân bố type trong bộ nhớ, biên dịch CIL
tương ứng thành mã máy trên platform cụ thể, thực hiện một số kiểm tra
bảo mật, và chạy chương trình.
Ngoài ra để tải các assembly và các kiểu của bạn, CLR sẽ tương tác với

các kiểu của .NET base class library khi cần. Mặc dù toàn bộ base class


C# và .NET Framework

library được chia nhỏ ra thành nhiều assembly cụ thể, nhưng assembly
chính yếu là mscorlib.dll. mscorlib.dll chứa một số lượng lớn các core
type bao gồm một lượng lớn các task cũng như các core data type được
sử dụng bởi tất cả ngôn ngữ .NET. Khi bạn build .NET solution bạn sẽ
tự động truy cập và assembly này độc lập.
Hình dưới đây mô tả workflow thực hiện giữa source code của bạn (có
sử dụng base class library), trình biên dịch .NET, và .NET execution
engine.

Phân Biệt Assembly, Namespace và Type
Chúng ta đều đã hiển sự quan trọng của các library. Mục tiêu của các thư
viện như MFC, J2EE và ATL là để giúp lập trìh viên có được một phần
code tốt khi xây dựng ứng dụng của họ. Tuy nhiên ngôn ngữ C# không
có một thư viện riêng nào, thay vào đó lập trình C# sử dụng các thư viện
.NET trung lập. Để giữ cho tất cả các kiểu trong base class library được
tổ chức tốt, .NET platform sử dụng khái niệm namespace.


C# và .NET Framework

Đơn giản namespace chỉ làm nhiệm vụ nhóm các kiểu có liên quan trong
một assembly lại. Ví dụ, trong System.IO namespace chứa các kiểu liên
quan đến việc đọc xuất tập tin, còn System.Data namespace thì chứa các
kiểu để làm việc với cơ sở dữ liệu. Và cần phải nhấn mạnh là một
assembly (như mscorlib.dll) có thể chứa được nhiều namespace, mỗi

namespace lại có thể chứa được nhiều kiểu.
Để thấy rõ hơn, hình dưới đây là chức năng Objet Browser của Visual
Studio 2005. Công cụ này cho phép bạn khảo sát các assembly đang
được project của bạn tham chiếu đến. Chú ý rằng mscorlib.dll chứa rất
nhiều namespace, và mỗi cái lại chứa rất nhiều lớp.

Điểm khác biệt chính của tiếp cận này và một thư viện dùng cho ngôn
ngữ cụ thể như MFC là bất cứ ngôn ngữ .NET nào cũng có thể sử dụng
cùng namespace và cùng kiểu. Ví dụ, ứng dụng “Hello World” kinh điển
được viết bằng C#, VB.NET và Managed Extensions for C++ như sau:


C# và .NET Framework

Code:
// Hello world in C#
using System;
public class MyApp
{
static void Main()
{
Console.WriteLine("Hi from C#");
}
}
' Hello world in VB .NET
Imports System
Public Module MyApp
Sub Main()
Console.WriteLine("Hi from VB .NET")
End Sub

End Module
// Hello world in Managed Extensions for C++
#include "stdafx.h"
using namespace System;
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"Hi from managed C++");
return 0;
}
Namespace System là namespace cơ bản nhất chứa các kiểu cơ bản mà
bạn sẽ luôn luôn đụng tới khi là một lập trình viên C#. Mà thật ra, bạn
chẳng thể làm gì cả nếu không dùng System namespace.
Truy Xuất Một Namespace
Xem lại namespace System. Từ quan điểm của bạn, bạn có thể đoán ra
rằng System.Console đại diện cho lớp tên là Console và được chứa trong


C# và .NET Framework

namespace gọi là System. Tuy nhiên, với .NET runtime, mọi chuyện
không phải vậy. Runtime engine chỉ thấy duy nhất một thực thể tên là
System.Console
Trong C#, từ khóa using đã đơn giản hóa quy trình tham chiếu đến các
kiểu được định nghĩa trong một namespace nào đó. Ví dụ:
Code:
using System;
// General base class library types.
using System.Drawing;
// Graphical rendering types.
using System.Windows.Forms;

// GUI widget types.
using System.Data;
// General data-centric types.
using System.Data.SqlClient;
// MS SQL Server data access types.
Một khi bạn đã sử dụng một số namespace, bạn sẽ tùy nghi tạo ra các
đối tượng của các kiểu trong namespace đó. Ví dụ nếu bạn muốn tạo
một đối tượng Bitmap (được định nghĩa trong System.Drawing
namespace), bạn có thể viết:
Code:
// Khai báo các namespace.
using System;
using System.Drawing;
class MyApp
{
public void DisplayLogo()
{
// Tạo một bitmap 20_20 pixel.
Bitmap companyLogo = new Bitmap(20, 20);
...
}
}
Vì bạn đã khai báo sử dụng namespace System.Drawing, trình biên dịch
sẽ tự động biết Bitmap thuộc vào namespace này. Nếu bạn không khai


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×