
Những chủ đề tiến bộ trong C#
Các ép kiểu do người dùng định
nghĩa – Phần 2
Ép kiểu giữa lớp dẫn xuất và lớp cơ sở
Để xem làm thế nào việc ép kiểu này làm, ta xem xét 2 lớp Mybase và
Myderived , trong đó Mydrived được dẫn xuất trực tiếp hoặc gián tiếp từ lớp
cơ sở
đầu tiên từ lớp Myderived đến Mybase ; luôn luôn ( giả sử hàm dựng có giá
trị)có thể viết :
MyDerived derivedObject = new MyDerived();
MyBase baseCopy = derivedObject;
Trong trường hợp này,chúng ta ép kiểu không tường minh từ myderived đến
mybase. điều này làm việc bởi vì luật là bất kì tham chiếu đến 1 kiểu mybase
được cho phép để chuyển thành đối tượng của lớp mybase hoặc đến đối
tượng bất kì được dẫn xuất từ lớp mybase.trong ngôn ngữ lập trình hướng
đối tượng, thể hiện của lớp dẫn xuất là thể hiện của một lớp cơ sở cộng thêm

với một thứ gì đó thêm. tất cả chức năng và thuộc tính được định nghĩa trong
lớp cơ sở cũng được định nghĩa trong lớp dẫn xuất .
Bây giờ ta có thể viết
MyBase derivedObject = new MyDerived();
MyBase baseObject = new MyBase();
MyDerived derivedCopy1 = (MyDerived) derivedObject; // OK
MyDerived derivedCopy2 = (MyDerived) baseObject;
Tất cả các câu lệnh trên là hợp lệ trong C# và minh họa việc ép kiểu từ lớp
cơ sở sang lớp dẫn xuất. tuy nhiên câu lệnh cuối sẽ tung ra biệt lệ khi thực
thi.
Chú ý rằng những lệnh ép kiểu mà trình biên dịch cung cấp , mà chuyển
giữa lớp cơ sở và lớp dẫn xuất thì không thực sự chuyển bất cứ dữ liệu nào
trên các đối tượng.tất cả chúng làm là thiết lập một sự tham chiếu mới để
quy cho một đối tượng nếu nó hợp lệ cho việc chuyển đổi .những lệnh ép
kiểu này thì rất khác trong tự nhiên từ những cái mà ta thường xuyên tự định
nghĩa.ví dụ, trong ví dụ Simplecurrency chúng ta định nghĩa việc ép kiểu là
chuyển giữa 1 kiểu tiền tệ sang kiểu số thực. trong ép kiểu thực-thành-
currency, chúng ta thực sự tạo một cấu trúc currency mới và khởi tạo nó với
giá trị được yêu cầu .những lệnh ép kiểu tiền định nghĩa giữa những lớp cơ s

ở và lớp dẫn xuất không làm điều này.nếu ta thực sự chuyển 1 thể hiện
Mybase thành một đối tượng Myderived thực với giá trị dựa trên nội dung
của thể hiện Mybase, ta sẽ không thể sử dụng cú pháp ép kiểu để làm điều
này.tuỳ chọn hợp lí nhất là thường xuyên định nghĩa 1 hàm dựng của lớp
dẫn xuất mà lấy thể hiện của lớp cơ sở như là 1 thông số và có hàm dựng
này biểu diễn việc khởi tạo chính xác:
class DerivedClass : BaseClass
{
public DerivedClass(BaseClass rhs)
{
// khởi tạo đối tượng từ thể hiện Base
}
// etc.
Ép kiểu boxing và unboxing
Ví dụ với cấu trúc currency:
Currency balance = new Currency(40,0);
object baseCopy = balance;

Khi ép kiểu không tường minh trên được thực hiện nội dung của balance
được sao chép vào heap trong đối tượng box và đối tượng basecopy tham
khảo đến đối tượng này.khi chúng ta định nghĩa cấu trúc currency , .net
framework cung cấp không tường minh một lớp ( ẩn) khác , một lớp
currency boxed, mà chứa đựng tất cả các trường như là cấu trúc currency
nhưng là kiểu tham chiếu lưu trong heap.điều này xảy ra bất cứ khi nào
chúng ta định nghĩa một kiểu dữ liệu- dù đó là struct hay kiểu liệt kê ( enum)
,và kiểu tham khảo boxed tồn tại đáp ứng đến tất cả kiểu dữ liệu nguyên
thuỷ int,double,uint, và ...ta không thể truy nhập vào các lớp này nhưng
chúng sẽ làm việc bất cứ khi nào có việc ép kiểu thành đối tượng khi chúng
ta ép kiểu currency thành đối tượng một thể hiện currency boxed tạo ra và
khởi tạo với tất cả các giá trị từ cấu trúc currency. trong ví dụ trên basecopy
sẽ tham khảo đến lớp currency boxed.
Ép kiểu còn được biết đến như là unboxing,dùng cho việc ép kiểu giữa
những lớp kiểu tham chiếu cơ sở và kiểu tham chiếu dẫn xuất.đó là ép kiểu
tường minh, bởi vì 1 biệt lệ sẽ được tung ra nếu đối tượng được ép kiểu
không ép đúng.
object derivedObject = new Currency(40,0);
object baseObject = new object();
Currency derivedCopy1 = (Currency)derivedObject; // OK

Currency derivedCopy2 = (Currency)baseObject; // Exception thrown
Khi sử dụng boxing và unboxing điều quan trọng để hiểu là cả hai tiến trình
này thực sự sao chép dữ liệu vào một đối tượng boxed hay unboxed. chính
vì lí do đó, thao tác trên đối tượng hộp sẽ không tácđộng đến nội dung của
kiểu dữ liệu nguyên thuỷ.
Multiple casting
Ví dụ với cấu trúc currency , giả sử trình biên dịch chạm trán với các dòng
mã sau:
Currency balance = new Currency(10,50);
long amount = (long)balance;
double amountD = balance;
Đầu tiên chúng ta khởi tạo 1 thể hiện currency ,sau đó ép nó thành kiểu
long.vấn đề là ta chưa định nghĩa ép kiểu cho việc này. tuy nhiên đoạn mã
nay vẫn biên dịch thành công bởi vì trình biên dịch nhận ra rằng ta đã định
nghĩa ép kiểu không tường minh để chuyển currency thành float.và nó biết
cách chuyển tường minh từ float sang long. ví lí do đó, nó sẽ biên dịch đầu
tiên là chuyển balance sang float rồi từ float sang long.tương tự cho kiểu
double tuy nhiên do chuyển tử float sang double không tường minh , do đó
chúng ta có thể viết lại tường minh :

