2012-01-07 36 views
8

Tôi đang gặp khó khăn khi hiểu điều này. Hãy xem xét ví dụ sau:C# - Các vấn đề với tính năng giải trí/unboxing/typecasting ints. Tôi không hiểu

protected void Page_Load(object sender, EventArgs e) 
{ 
    // No surprise that this works 
    Int16 firstTest = Convert.ToInt16(0); 
    int firstTest2 = (int)firstTest; 

    // This also works 
    object secondTest = 0; 
    int secondTest2 = (int)secondTest; 

    // But this fails! 
    object thirdTest = Convert.ToInt16(0); 
    int thirdtest2 = (int)thirdTest; // It blows up on this line. 
} 

Các lỗi cụ thể mà tôi có được trong thời gian chạy là Specified cast is not valid. Nếu tôi QuickWatch (int)thirdTest trong Visual Studio, tôi nhận được một giá trị của Cannot unbox 'thirdTest' as a 'int'.

Điều gì đang xảy ra ở đây?

+1

Int16 thực sự là một đoạn ngắn. Vì vậy, tôi nghĩ bạn có thể thay thế 'Int16 firstTest = Convert.ToInt16 (0);' với 'Int16 firstTest = 0s;' –

Trả lời

12

Kiểm tra hộp kiểm loại chính xác như được giải thích trong documentation.

Unboxing là một chuyển đổi rõ ràng từ các đối tượng loại một loại giá trị hoặc từ một kiểu giao diện cho một kiểu giá trị mà thực hiện giao diện . Một hoạt động unboxing gồm:

  • Kiểm tra trường hợp đối tượng để đảm bảo rằng nó là một giá trị đóng hộp của các loại giá trị nhất định.

  • Sao chép giá trị từ cá thể vào biến loại giá trị.

Như bạn có thể thấy bước đầu tiên là để kiểm tra xem trường hợp đối tượng phù hợp với loại mục tiêu.

Cũng trích dẫn từ tài liệu:

Đối với unboxing của kiểu giá trị để thành công tại thời gian chạy, mục là không có hộp bọc phải là một tham chiếu đến một đối tượng mà trước đó đã được tạo ra bởi đấm bốc một thể hiện của loại giá trị đó. Cố gắng unbox null gây ra một NullReferenceException. Cố gắng hủy liên kết một tham chiếu đến một loại giá trị không tương thích gây ra một InvalidCastException.

Vì vậy, để khắc phục lỗi này đảm bảo rằng các loại phù hợp trước khi cố gắng Unbox:

object thirdTest = Convert.ToInt16(0); 
short thirdtest2 = (short)thirdTest; 
+2

Hoặc bỏ hộp với loại chính xác, sau đó truyền đến loại bạn muốn. 'int thirdtest2 = (int) (ngắn) thirdTest;' –

9

gì đang xảy ra là chính xác những gì nó nói.

Trong trường hợp đầu tiên, bạn có một đoạn mã ngắn, không được đóng hộp, sau đó bạn định kiểu một cách rõ ràng vào một int. Đây là một chuyển đổi hợp lệ mà trình biên dịch biết cách làm, vì vậy nó hoạt động.

Trong trường hợp thứ hai, bạn có một int, đóng hộp, được gán trở lại một int. Đây là một unboxing đơn giản của một số nguyên, cũng hợp lệ, do đó, nó hoạt động.

Trong trường hợp thứ ba, bạn có một đoạn ngắn, đóng hộp, bạn đang cố gắng bỏ hộp thư thành một biến không ngắn. Đây không phải là một hoạt động hợp lệ: bạn không thể làm điều này trong một bước.Đây không phải là một vấn đề phổ biến, hoặc là: nếu bạn đang sử dụng, ví dụ, một SqlDataReader có chứa một cột SMALLINT, bạn không thể làm:

int x = (int)rdr["SmallIntColumn"]; 

Hoặc những điều sau đây nên làm việc trong ví dụ thứ ba của bạn:

object thirdTest = Convert.ToInt16(0); 
    int thirdTest2 = Convert.ToInt32(thirdTest); 
    int thirdTest3 = (int)(short)thirdTest; 
4

Int16 là cách ưa thích để viết short; không có boxing/unboxing đang diễn ra ở đó, chỉ cần chuyển đổi CLR đơn giản giữa các số nguyên 16 bit và 32 bit.

Hộp trường hợp thứ hai và hộp mở cùng loại, được cho phép: loại giá trị int được gói trong một object và sau đó được mở.

Trường hợp thứ ba cố gắng bỏ hộp thư đến loại khác nhau (int thay vì short) không được phép.