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

Tài liệu C# và kiến trúc .NET part 5 docx

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 (191.32 KB, 11 trang )


Tìm hiểu về Intermediate Language
Như chúng ta đã biết, Intermediate Language hoạt động như là bản chất của .NET
Framework. Là lập trình viên C#, chúng ta nên biết rằng mã C# sẽ luôn được dịch sang
Intermediate Language trước khi nó được thực thi (thật vậy, trình biên dịch C# chỉ dịch
sang mã có quản). Chúng ta hãy cùng khám phá các tính năng chính của IL, bất kì ngôn
ngữ nào hướng .NET cũng sẽ hỗ trợ các đặc tính chính của IL.
Sau đây là những đặc tính chính của Intermediate Language:
• Hướng đối tượng và dùng interfaces
• Sự tách biệt giữa kiểu giá trị và kiểu tham chiếu
• Định kiểu mạnh
• Quản lỗi thông qua các ngoại lệ
• Sự dụng các thuộc tính
Bây giờ chúng ta sẽ cùng khám phá các đặc tính trên.
Hỗ trợ hướng đối tượng và dùng giao diện
Ngôn ngữ độc lập nền của .NET có một vài giới hạn riêng. Cụ thể trong lúc thực thi IL
chắc chắn sẽ thực thi một cách thức lập trình riêng, và các ngôn ngữ khác phải chú ý đến
việc tương thích với cách thức lập trình này. IL đã được Microsoft phát triển như là một
ngôn ngữ hướng đối tượ
ng cổ điển hỗ trợ đầy đủ thừa kế đơn giữa các lớp.
Bên cạnh lập trình hướng đối tượng đơn, Intermediate Language còn nêu ra ý tưởng về
interfaces (giao diện), cái đã được tích hợp trong Windows với giao diện COM. .NET nó
không giống như giao diện COM; chúng không cần phải hỗ trợ bất kì một kiến trúc COM
nào (ví dụ, chúng không xuất phát từ IUnknown, và chúng cũng không liên quan gì đến
các GUID). Tuy nhiên chúng có thể dùng chung các giao diện COM.
Hướng đối tượng và thực thi chéo ngôn ng

Bây chúng ta sẽ tìm hiểu về hoạt động của .NET nghĩa là hoạt động biên dịch sang mã
Intermediate Language, điều đó nói lên rằng bạn cần phải lập trình theo cách thức hướng
đối tượng truyền thống. Không những thế chúng còn cung cấp cho chúng ta khả năng
chuyển giao ngôn ngữ. Sau cùng, C++ và Java cả hai đều dùng những biến thể của hướng


đối tượng, dù vậy chúng vẫn còn được quan tâm để có thể thực thi chéo. Chúng ta cần
tìm hiể
u một chút về thực thi chéo ngôn ngữ.
Trước tiên chúng ta cần hiểu chính xác thực thi ngôn ngữ chéo là gì. Sau cùng, COM cho
phép các thành phần được viết bởi các ngôn ngữ khác nhau có thể thực thi chéo. COM, là
một nhị phân chuẩn, cho phép các thành phần có thể hiểu nhau và có thể gọi các phương
thức cũng như thuộc tính lẫn nhau mà không cần quan tâm đến ngôn ngữ đã tạo ra chúng.
Để làm được điều đó mỗi đối tượng phải có khả năng giao tiếp với thời gian chạy của
COM, và phải có khả năng truy cập thông qua một giao diện. Các thành phần chỉ có thể
giao tiếp với nhau trong thời gian chạy COM. Dù rằ
ng các thành phần của COM có thể
giao tiếp với nhau bất chấp ngôn ngữ đã tạo ra chúng, tuy nhiên COM không hỗ trợ hoạt
động thừa kế, chính vì thế nó đã đánh mất các thuận lợi của lập trình hướng đối tượng.
Một vấn đề xảy ra khi bẫy lỗi là các thành thành phần phải được bẫy lỗi trong ngôn ngữ
đã tạo chúng, và bạn không thể bẫy lỗi từng bước trên các ngôn ngữ khác nhau. Vậy th
ực
thi chéo ngôn ngữ được hiểu như là các lớp được tạo ra trong một ngôn ngữ có thể giao
tiếp lẫn nhau với các lớp được tạo ra trong các ngôn ngữ khác. Cụ thể là:
• Một lớp được tạo ra trong một ngôn ngữ có thể thừa kế từ một lớp được viết trong
một ngôn ngữ khác.
• Một lớp có thể chứa thể hiện của một lớp khác không quan tâm đến ngôn ngữ đã
tạo ra hai lớp đó.
• Một đối tượng có thể gọi trực tiếp phương thức của một đối tượng khác được viết
bởi một ngôn ngữ khác.
• Các đối tượng (hoặc các tham chiếu đến các đối tượng) có thể được truyền qua lại
giữa các hàm
• Bạn có khả năng bẫy lỗi từng bước chương trình nguồn giữa các ngôn khác nhau
Thật bất ngờ về những gì mà .NET và thực thi ngôn ngữ chéo đã làm được. Tiện ích bẫy
lỗi từng được giới thiệu như là khả năng của Visual Studio .NET IDE hơn là CLR.
Sự khác biệt giữa kiểu dữ liệu giá trị và kiểu dữ liệu tham chiếu

Như bất kì ngôn ngữ lập trình nào, IL cung cấp một s
ố tiền định nghĩa về các kiểu dữ liệu
nguyên thủy. Một đặc trưng của Intermediate Language là phân biệt rạch ròi giữa kiểu dữ
liệu giá trị và kiểu dữ liệu tham chiếu. Kiểu giá trị là các biến được dùng để lưu trực tiếp
giá trị, trong khi đó kiểu tham chiếu là các biến chứa địa chỉ của dữ liệu.
Trong C++, kiểu tham chiếu có thể coi như là m
ột con trỏ, trong khi đó ở Visual Basic,
kiểu tham chiếu có thể coi là các đối tượng, trong VB 6 luôn truy cập thông qua tham
chiếu. Intermediate Language cũng chỉ rõ về cách thức lưu trữ dữ liệu: ví như một kiểu
tham chiếu luôn được lưu trong vùng managed heap của bộ nhớ, trong khi đó kiểu giá trị
lại được lưu trong stack (tuy nhiên nếu kiểu dữ liệu được khai báo là một trường của kiểu
tham chiếu, chúng vẫn được l
ưu ở heap). Chúng ta sẽ bàn về stack và heap trong chương
3.
Định kiểu mạnh
Một điểm mạnh trong IL là định kiểu mạnh. Nghĩa là tất cả các biếu đều được đánh dấu
rõ ràng và chuyên biệt về kiểu dữ liệu (IL không còn hỗ trợ kiễu Variant cho Visual
Basic và ngôn ngữ kịch bản). Cụ thể là IL không cho phép các hoạt động trả về các kiểu
dữ liệu không rõ ràng.
Trong trường hợp là người phát triển VB có lẽ bạn sẽ rất lo lắng về kiểu, bởi vì khi dùng
kiể
u dữ liệu Variant VB tự động ép kiểu giúp bạn. Còn là người phát triển C++, có lẽ bạn
sẽ dùng các casting pointer giữa các kiểu. Lập trình theo cách này có thể là một lập trình
mạnh, tuy nhiên nó phá vỡ tính an toàn kiểu. Từ bây giờ, nó chỉ còn hỗ trợ trong những
trường hợp đặc biệt trong một số ngôn ngữ có khả năng biên dịch sang mã có quản. Thật
vậy, các con trỏ (không phải là tham chiếu) chỉ còn cho phép trong các khối mã đặc biệt
trong C#, trong VB không có (mặc dù nó cho phép trong C++). Nế
u dùng con trỏ trong
mã nguồn nó sẽ không chuyển thành mã có quản và sẽ không được kiểm tra bởi CLR.
Bạn cũng nên biết rằng trong một số ngôn ngữ biết .NET, chẳng hạn như VB.NET, vẫn

cho phép mơ hồ kiểu, tuy nhiên chỉ để có thể làm được như thể làm được như vậy thì
trình biên dịch đã xác định kiểu bảo vệ kiểu trước khi phát ra IL.
Mặc dù, kiểu bảo vệ lúc đầu có thể sinh ra nhiề
u cản trở trong lập trình nhưng trong
nhiều trường hợp kiểu bảo vệ sẽ mang lại nhiều lợi ích to lớn trong các dịch vụ được
cung cấp bởi .NET. Chẳng hạn các dịch vụ sau:
• Language Interoperability
• Garbage Collection
• Security
• Application Domains
Hãy tìm hiểu xem tại sao kiểu dữ liệu mạnh lại là một trong những đặc tính quan trọng
của .NET.
Tầm quan trọng của Strong Data Typing đối với Language Interoperability
Một khía cạnh quan trong của strong data typing là nếu một lớp xuất thân hoặc chứa
một lớp khác thì nó cần phải biết tất cả các kiểu dùng trong các lớp đó. Thật vậy, nó đã
từng các chướng ngại lớn trong việc thực thi ngôn ngữ chéo
ở các hệ thống không hỗ trợ
trước đấy. Thông tin này không có sẵn trong các file thi hành và DLL chuẩn.
Giả sử rằng một phương thức trong VB.NET được định nghĩa là sẽ trả về một Integer,
một trong những kiểu dữ liệu chuẩn của VB.NET. C# không có kiểu dữ liệu có tên như
vậy. Chúng ta chỉ có thể dùng phương thức này để trả về một kiểu của C# nết trình biên
dịch biết cách ánh xạ
kiểu VB.NET's Integer đến một trong những kiểu được định nghĩa
trong C#. Vậy .NET đã làm việc đó như thế nào?
Common Type System (CTS)
Vấn đề về kiểu dữ liệu này được .NET giải quyết bằng cách dùng Common Type
System (CTS). CTS định nghĩa các kiểu dữ liệu tiền định và có sẵn trong IL, vì thế tất
các các ngôn ngữ hướng .NET framework sẽ sinh ra mã cuối trên cơ sở các kiểu dữ liệu
này.
Trong ví dụ trên, VB.NET's Integer thực tế là một 32-bit signed integer, được ánh xạ từ

kiểu Int32 trong IL. Nó phải được biên dịch thành mã IL. Bởi vì trình biên dịch C# cũng
biết ki
ểu dữ liệu này nên không có vấn đề gì cả. Ở cấp mã nguồn, C# gọi Int32 là int, vì
vậy khi biên dịch hàm VB.NET đơn giản trả về một kiểu int.
CTS không chỉ đơn thuần là các kiểu dữ liệu đơn giản, doesn't merely specify primitive
data types, mà nó còn cho phép chúng ta tự định nghĩa kiểu của riêng mình.
Các kiểu được trình bày trong bảng dưới đây:
Kiểu Giải thích
Type Kiểu cơ bản dùng để mô tả các kiểu khác
Value Type Kiểu cơ bản dùng để mô tả các kiểu giá trị.
Reference Types Kiểu cơ bản dùng để môt tả các kiểu tham trị.
Built-in Value Types Bao gồm các kiểu giá trị nguyên thủy chuẩn, như các kiểu
số, kiểu luận lí, kiểu kí tự.
Enumerations Bộ các giá trị liệt kêSets of enumerated values.
User-defined Value Types Kiểu được định nghĩa trong mã nguồn như là một kiểu giá
trị. Trong C# nó có là struct.
Interface Types Các giao diện.
Pointer Types Các con trỏ.
Self-describing Types Kiểu dữ liệu có quản.
Arrays Các kiểu chứa mảng các đối tượng.
Class Types Các kiểu tự mô tả nhưng không phải là mảng.
Delegates Kiểu được thiết kế để tham chiếu đến các phương thức.
User-defined Reference
Types
Kiểu được định nghĩa trong mã nguồn và được lưu như là
kiểu tham chiếu. Trong C#, nó có nghĩa là một lớp.
Boxed Value Types Một kiểu giá trị được bọc thành một kiểu tham chiếu vì thế
nó có thể được lưu trong heap.
Chúng ta không thể liệt kê tât cả các kiểu giá trị ở đây, bởi vì chúng sẽ được bàn kĩ trong
chương 2. Trong C#, mỗi kiểu có sẵn được nhận dạng bởi trình biên dịch ánh xạ đến một

kiểu IL cài sẵn. Điều này cũng đúng cho cả VB.NET.
Common Language Specification (CLS)
Common Language Specification hoạt động cùng với Common Type System để bảo đảm
thực thi ngôn ngữ chéo. CLS là một bộ con chuẩn mà tất cả các trình biên dịch hướng
.NET đều phả
i hỗ trợ. Đều đó có nghĩa là các trình biên dịch đều sẽ hỗ trợ tất cả những gì
được định nghĩa trong CLS.
Chú ý: Các bạn có thể viết các mã non-CLS, tuy nhiên những mã này không đảm bảo
việc thực thi ngôn ngữ chéo.
IL là một ngôn ngữ phân biệt loại kí tự. Những nhà phát triển khi làm việc với các ngôn
ngữ phân biệt loại kí tự có khả năng tạo nên sự mềm dẻo khi đặt tên biến. VB.NET, lại
không phả
i là ngôn ngữ phân biệt loại kí tự. CLS xử lí việc này bằng các ra hiệu cho
CLS rằng mã không cho phép hai tên chỉ khác nhau về mặt loại kí tự. Bởi vậy, mã
VB.NET có thể hoạt động trong CLS.
CLS hoạt động theo hai định hướng. Trước tiên nó là một trình biên dịch riêng không hỗ
trợ đây đủ các đặc trưng của .NET điều này khuyến khích sự phát triển của các ngôn biết
.NET khác. Thứ hai, nó bảo đảm rằng nếu bạn hạn chế
các lớp của bạn trong những đặc
tính của CLS, thì nó bảo đảm rằng các mã dùng trong những ngôn ngữ khác có thể dùng
các lớp này.
Nét đẹp của ý tưởng này là việc giới hạn trong những đặc tính của CLS chỉ nên áp dụng
cho những thành phần public và protected của các lớp và chỉ dùng cho các lớp public.
Trong các thành phần thực thi của các lớp của bạn, bạn có thể viết các mã non-CLS nếu
muốn, bởi các ngôn ngữ khác không bao giờ có thể truy cập vào những ph
ần này.
Chúng ta không đi vào chi tiết của CLS ở đây. Về mặt tổng quát CLS không ảnh hưởng
nhiều đến mã C# của bạn vì nó không có nhiều đặc tính khác CLS.
Garbage Collection
Garbage collector là một thành phần quản lí bộ nhớ của .NET, nó là một đáp án cho việc

thu hồi bộ nhớ của các chương trình thực thi. Từ trước đến giờ có hai công nghệ được sử
dụng cho việc huỷ bộ nhớ trong Windows, những tiến trình này được yêu c
ầu từ hệ
thống:
• Ứng dụng tự làm điều này một cách thủ công.
• Tạo một bộ đếm tham chiếu đến đối tượng.
Việc mã ứng dụng chịu trách nhiệm thu hồi vùng nhớ là một cộng nghệ dùng ở mức thấp,
hoặc những ngôn ngữ thực thi cấp cao như C++. Nó mang tính hiệu quả cao, nó có thuận
lợi là tài nguyên sẽ được giải phóng ngay khi không còn cần thiết. Một bất lợi lớn là nó
thường xuyên sinh lỗi. Mã nguồn luôn phải chỉ rõ cho hệ thống biết khi nó không cần
dùng bộ nhớ đó nữa . Dễ dàng nhìn ra rằng kết qu
ả có thể dẫn đến rò rỉ bộ nhớ.
Mặc dù các môi trường phát triển hiện đại có cung cấp một số công cụ giúp đỡ trong việc
phát hiện sự rò rỉ bộ nhớ, nhưng rất khó theo vết, bởi vì nó không có hiệu lực cho đến khi
có một khối lượng lớn bộ nhớ bị rò rỉ: Windows buộc phải ngưng các tiến trình xử lí. Tại
thời điểm này máy tính chậm đ
i thấy rõ một sự trả giá cho các yêu cầu bộ nhớ.
Việc duy trì một bộ đếm các tham chiếu là một ân huệ trong COM. Ý tưởng này cho rằng
mỗi thành phần COM chứa một bộ đếm xem có bao nhiêu ứng dụng đang chứa tham
chiếu đến nó. Khi bộ đếm này xuống đến zero, Thành phần có thể tự hủy nó và giải
phóng vùng nhớ cũng như các tài nguyên tương ứng. Vấn đề ở đây là nó vẫn lệ thu
ộc vào
sự thông báo của các ứng dụng khi chúng không còn dùng đến các thành phần này nữa.
Trong một vài trường hợp, nó có khả năng tạo ra một vấn đề nghiêm trọng hơn là sự kiểu
rò rỉ C++ thông thường, bởi vì đối tượng COM có thể nằm trong một tiến trình của riêng
nó, điều này có nghĩa là nó sẽ không bao giờ được hủy bởi hệ thống (chí ít trong rò rỉ
kiểu C++, hệ thống có thể giành lại toàn bộ vùng nh
ớ khi tiến trình kết thúc).
Thời gian chạy .NET hoàn toàn phụ thuộc vào garbage collector instead. Đây là một
chương trình hỗ trợ việc thu dọn bộ nhớ. Trong ý tưởng này tất cả các yêu cầu bộ nhớ

đều được cấp phát trên heap (điều này đúng cho tất cả các ngôn ngữ, trong .NET, CLR
chứa nó trong vùng heap có quản cho tất cả các ứng dụng .NET sử dụng). Thỉnh thoảng
.NET sẽ kiểm tra xem vùng heap có quản có trở nên đầy chưa để
nó tiến hành thu dọn, và
nó gọi đây là tiến trình thu gôm rác. Trình thu dọn rác sẽ kiểm tra các tham chiếu từ mã
của bạn, ví dụ các tham chiếu từ mã của bạn đến các đối tượng được lưu trên heap được
nhận dạng, nó có nghĩa là đối tượng đó vẫn còn tham chiếu, các đối tượng không còn
tham chiếu nữa sẽ bị huỷ.
Trình thu gom rác hoạt động trong .NET bởi vì Intermediate Language được thiết kế để
làm điều
đó. Phải tuân thủ các nguyên tắc sau, thứ nhất bạn chỉ có thể tham chiếu đến
một đối tượng có sẵn bằng cách sao chép cac tham chiếu có sẵn, thứ hai Intermediate
Language bảo vệ kiểu, điều này có nghĩa là các tham chiếu đến các đối tượng có sẵn luôn
chứa đựng thông tín nhận dạng chính xác của đối tượng đó.
C++ Có thể không sử dụng trình thu gom một cách máy móc, bởi vì C++ cho phép các
con trỏ tự do ép kiểu.
Một đ
iều đặc biệt quản trọng là tính không định trước của trình thu gom rác. Hay nói
cách khác, bạn không thể bảo đảm được khi nào trình thu gôm rác sẽ được gọi; nó sẽ
được gọi khi CLR cảm thấy cần (nếu bạn không thực hiện lời gọi tường minh).
Bảo mật
.NET thật sự xuất sắc trong việc bổ sung cơ chế bảo mật của Windows bởi vì nó hỗ trợ
code-based security trong khi đó Windows chỉ thật sự hỗ trợ Role-based security.
Role-based security là cơ sở để xác định tài khoản của các tiến trình đang thực thi, hay
nói cách khác ai sở hữu các tiến trình đang thực thi. Code-based security là một cơ chế
khác để xác định xem những mã nào và có bao nhiêu mã là đáng tin. Cảm ơn sự
bảo vệ
kiểu mạnh của IL, vì nhờ nó mà CLR có thể kiểm tra mã trước khi chạy trong một chế độ
bảo vệ được đưa ra.NET cũng hỗ trợ một cơ chế những mã nào được phép phơi tra trong
một cơ chế bảo mật nào đó.

Một điều quan trọng là code-based security có thể làm giảm nguy cơ liên quan đến việc
chạy các đoạn mã có xuất xứ không rõ ràng (chẳ
ng hạn như mã mà bạn downloaded từ
Internet). Một ví dụ, nếu mã được chạy dưới quyền administrator, nó có thể sử dụng
code-based security để khai báo rằng mã không còn cho phép thực thi trong những kiểu
mà quyền administrator hỗ trợ như: không thể đọc hoặc viết lên các biến môi trường, đọc
hoặc viết lên registry, không truy cập vào các đặc trưng trong .NET.
Security sẽ được bàn kĩ hơn trong chương 23.
Application Domains
Application domains là một cách tân quan trọng trong .NET và nó được thiết kế để có thể

dễ dàng xử li các vấn đề khi chạy các ứng dụng cần sự biệt lập với các ứng dụng khác
nhưng vẫn có thể thông tin với các ứng dụng khác. Một ví dụ cổ điển đó lá một ứng dụng
web server application, nó phải phản hồi lại với một số lượng các yêu cấu từ các trình
duyệt. Chắc chắn rằng sẽ tồn tại cùng lúc nhiều thành phần có kh
ả năng phản hồi để phục
vụ cho các yêu cầu đó.
Trước thời .NET, sự lựa chọn giữa cho phép các thể hiện đó có thể dùng trong một tiến
trình, cái mà sẽ mang lại sự rủi ro có thể làm giảm độ an toàn của trang web, hay là cho
phép các thể hiện đó chạy trên các tiến trình biệt lập, cái mà sẽ mang lại sự gia tăng sự
thực thi.
Giờ đây, đó là sự biệt lậ
p mã thông qua các tiến trình. Khi bạn kích khởi một ứng dụng
mới, nó sẽ chạy trong ngữ cảnh của tiếnt trình. Các tiến trình Windows độc lập nhau
thông qua vùng địa chỉ. Trong ý tưởng này mỗi tiến trình sẽ có sẵn 4 gigabytes bộ nhớ ảo
để chữa dữ liệu và mã thực thi (4GB là dành cho hệ thống 32-bit; hệ thống 64-bit có thể
nhiều hơn). Windows gián tiếp thực hiện cơ chê mở rộng để ánh xạ bộ nhớ ả
o này với bộ
nhớ vật lí thật hay đĩa. Mỗi tiến trình sẽ có sự ánh xạ khác nhau, sao cho các vùng nhớ
vật lí thật sự không trùng lấp nhau. Nó được minh họa bởi sơ đồ sau:


Một cách tổng quat, bất kì tiến trình nào cũng chỉ có thể truy cập đến bộ nhớ thông qua
mộ địa chỉ ảo cụ thể - các tiến trình không thể truy xuất trực tiếp bộ nhớ vật lí. Như vậy
nó đơn giản là không cho phép một tiến trình có thể truy xuất đến vùng nhớ được cấp cho
một tiến trình khác. Nó cung cấp một cơ chế bảo đảm rằng những ứng x
ử tồi của mã
không thể làm hỏng bất kì thứ gì bên ngoài vùng địa chỉ của nó. (chú ý rằng trong
Windows 9x, những cơ chế bảo vệ này không đươc thấu đáo như trong NT/2000/XP, vì
thế về mặt lí thuyết các ứng dụng có khả năng phá hủy Windows do viết lên vùng nhớ
không thích hợp).
Các tiến trình không chỉ phục vụ như là cách để tạo nên sự tách biệt giữa các thể hiện
khác nhau. Trong hệ thống Windows NT/2000, nó còn làm đơn v
ị để gán các giấy phép
và đặc quyền bảo mật. Mỗi tiến trình có một kí hiệu bảo mật riêng, để báo cho Windows
biết chính xác các thực thi mà tiến trình cho phép.
Cả hai phương pháp này đều có khả năng bảo mật tốt nhưng lại sinh ra một bất lợi lớn đó
là thực thi. Thông thường các tiến trình sẽ hoạt động chung với nhau, bởi vậy cần phải có
sự truyền thông giữa chúng. Ví dụ như
đâu đó một tiến trình gọi một thành phần COM
khả thi, và bởi vì được yêu cầu chạy trong tiến trình của chúng. Giống như cách mà COM
vẫn làm. Khi đó các tiến trình không thể dùng chung bộ nhớ, một tiến trình phức tạp
được sử dụng để sao chép dữ liệu giữa các tiến trình. Nó sẽ gây trở ngại lớin đến vấn đề
thực thi. Nếu bạn muốn các thành phần có thể làm việc với nhau mà không mu
ốn ảnh
hưởng đến vấn đề thực thi, cách duy nhất là sử dụng DLL-based components và mọi thứ
sẽ hoạt động trong cùng một vùng đã chỉ (đây là một việc mạo hiểm vì các thành phần
ứng xử tồi sẽ làm hỏng tất cả mọi thứ).
Application domains được thiết kế như là một thành phần riêng biệt không gây ảnh
hưởng đến vấn đề thực thi trong lúc các tiến trình trao đổi d
ữ liệu. Ý tưởng này cho rằng

một tiến trình được chia thành một số các application domains. Mỗi application domain
sẽ trả lời cho một ứng dụng đơn, và các loạt thực thi sẽ hoạt động như là một application
domain độc lập:

Nếu các thực thi cúng sử dụng chung một vùng nhớ, rõ ràng chúng có thể dùng chung dữ
liệu, bởi vì trên lí thuyết chúng có thể truy xuất trục tiếp dữ liệu của nhau. Tuy nhiên đó
chỉ là nguyên tắc, CLR sẽ bảo đảm rằng
điều này sẽ không xảy ra trong thực tế bằng cách
kiểm tra kỹ lưỡng mã trong mỗi ứng dụng, để chắc rằng chúng không lạc ra khỏi vùng dữ
liệu của chúng. Trước tiên hầu như các trò bịp quá đáng sẽ bị loại bỏ, sau đó ứng dụng có
thể hoạt động và không phải kích hoạt nó.
Thật sự, nó hoàn toàn có thể làm được điều này vì sự định kiểu mạnh củ
a IL. Trong nhiều
trường hợp, nếu mã thật sự dùng kiểu không quản chẳng hạn như các con trỏ, kiểu dữ liệu
đang dùng sẽ bảo đảm vùng nhớ sẽ được truy cập hợp lí. ví dụ, kiểu mảng .NET sẽ tiến
hành kiểm tra và bảo đảm rằng các thao tác trên mảng đều nằm trong phạm vi cho phép.
Nếu một thực thi cần trao đổi thông tin với các thực thi chạy trong các application
domain khác chúng phải gọi dịch v
ụ điều khiển từ xa của .NET.
Mã được kiểm tra xem có truy cập dữ liệu ngoài application domain không được gọi là
memory type-safe. Như vậy mã này có thể hoạt động cùng với mã được bảo vệ ở các
application domains khác nhau trong cùng một tiến trình.
Bẫy lỗi thông qua các ngoại lệ
.NET được thiết kế để đơn giản hoá quá trình bẫy lỗi thông qua các ngoại lệ. Những nhà
phát triển C++ nên biết rằng, bởi vì IL là hệ thống định ki
ểu mạnh, nó không thực thi các
mối kết hợp bất lợi thông qua các ngoại lệ trong IL, đây là cách được đưa ra trong C++.
Tất nhiên khối finally cũng được hỗ trợ trong .NET và C#.
Chúng ta sẽ bàn kĩ về ngoại lệ trong chương 4. Sơ qua một chút, ý tưởng ở đây là một
vùng mã được thiết kế như là các thủ tục quản ngoại lệ, mỗi đoạn mã có thể giải quyết

một điêu kiện lỗi riêng (ví dụ, một file không được tìm thấy, hoặc không được phép thực
thi một số lệnh). Những điều kiện này có thể được định nghĩ
a kĩ hoặc sơ qua tuỳ bạn. Cấu
trúc ngoại lệ bảo đảm rằng khi một điều kiện sinh lỗi xảy ra, ngay lập tức luồn thi hành sẽ
nhảy đến thủ tục quản ngoại lệ.
Cơ cấu quản ngoại lệ tạo điều kiện thuận lợi để truyền cho một đối tượng thông tin chính
xác về các điều kiện sinh ngo
ại lệ và một thủ tục quản ngoại lệ. Đối tượng này có thể bao
gồm một thông điệp thích hợp cho người dùng và chi tiết về nơi phát sinh ngoại lệ.
Hầu hết các cơ cấu quản ngoại lệ, bao gồm cả điều khiển của chương trình sẽ treo khi
một ngoại lệ được phát sinh, được quản bởi ngôn ngữ bậc cao (C#, VB.NET, C++), và
không một lệnh IL nào hỗ
trợ việc đó. Ví dụ C#, quản sự kiện thông qua các khối mã
try{}, catch{}, finally{}, chúng ta sẽ bàn sau trong chương 4.
Những gì mà .NET làm là cung cấp cơ sở cho phép các trình biên dịch hướng .NET hỗ
trợ việc quản ngoại lệ. Cụ thể nó cung cấp một bộ các lớp .NET có thể miêu tả các ngoại
lệ, và thực thi ngôn ngữ chéo cho phép truyền các đối tượng ngoại lệ cho các mã quản
ngoại lệ, bất chấp mã quản ngoại lệ đượ
c viết trong ngôn ngữ nào. Sự độc lập ngôn ngữ
này không được hỗ trợ trong việc quản ngoại lệ của C++ lẫn Jave, mặc dù nó vẫn tồn tại
giới hạn trong cơ cấu COM cho việc quản lỗi: bao gồm việc trả về mã lỗi trong các
phương thức và truyền các đối tượng lỗi. Thật vậy các ngoại lệ đó được quản một cách
nhất quán trong các ngôn ngữ khác nhau nó đóng vai trò quy
ết định trong phát triển đa
ngôn ngữ.
Dùng các thuộc tính
Attributes là một đặc trưng đã thân thuộc với những nhà phát triển C++ để viết các thành
phần COM (thông qua việc sử dụng Microsoft's COM Interface Definition Language
(IDL)) dù vậy nó không thân thiện với những nhà phát triển Visual Basic hay Java.
Attribute cung cấp thông tin mở rộng liên quan đến các mục trong chương trình có thể

được sử dụng bởi trình biên dịch.
Attributes được hỗ trợ trong .NET - và vì thế giờ đây nó được hỗ trợ trong C++, C#, và
VB.NET. Một cái mới là các attribute trong .NET là một cơ chế cho phép bạn có thể định
nghĩa các attribute của riêng bạn trong mã nguồn. Các attribute tự định nghĩa này có thể
thay thế cho các siêu dữ liệu của các phương thức và kiểu dữ liệu tương ứng. .Do tính độc
lập ngôn ngữ của .NET mà các attribute có thể được định nghĩa trong một ngôn ngữ và
có thể đọc bằng mã ở các ngôn ngữ khác.
Attributes sẽ được bàn trong chương 5 của cuốn sách này.

×