2010-08-22 31 views
37

Tôi có đoạn mã sau:Hành vi truyền lạ. không thể cast đối tượng (int) để lâu

int intNumber1 = 100; 
object intNumber2 = 100; 
bool areNumberOfTheSameType = intNumber1.GetType() == intNumber2.GetType(); // TRUE 
bool areEqual = intNumber1.Equals(intNumber2); // TRUE 

long longNumber1 = (long) intNumber1; // OK 
long longNumber2 = (long) intNumber2; // InvalidCastException. Why? 

Tại sao không phải là công việc diễn viên thứ hai? Tôi nhận ra rằng có thể là do đối tượng không có dàn diễn viên rõ ràng trong một thời gian dài, nhưng nếu chúng ta xem xét loại của nó khi chạy là System.Int32.

Nếu tôi sử dụng var hoặc dynamic thay vì object, nó hoạt động.

Mọi suy nghĩ?

+4

hãy thử thay đổi điều đó thành 'long longNumber2 = (long) (int) intNumber2;' –

+0

Tại sao bạn muốn sử dụng đối tượng thay vì var trong trường hợp này? Tốt hơn là giữ cho các biến được gõ mạnh mẽ khi có thể –

+1

@ Quinn351: tôi đoán là mã trên minh họa một vấn đề đơn giản mà người dùng có, tôi không nghĩ chúng ta nên coi nó như một thực tế hiện tại. – Abel

Trả lời

42

Truyền từ int đến long được hiểu là chuyển đổi giữa hai loại.

Truyền từ object đến int được hiểu là mở hộp được đóng hộp int.

Đó là cú pháp tương tự, nhưng nó nói hai điều khác nhau.

Trong các trường hợp làm việc (intlong, object (đóng hộp int) → int), trình biên dịch biết chính xác những gì mã để sản xuất. Nếu đóng hộp intlong là để làm việc, trình biên dịch sẽ phải bằng cách nào đó tìm ra chuyển đổi để sử dụng, nhưng nó không có đủ thông tin để làm điều đó.

Xem thêm this blog post from Eric Lippert.

+2

@Bashir Magomedov: Bài đăng trên blog của Eric Lippert về điều này khá tốt, rất muốn bạn đọc nó. – R0MANARMY

+0

@ R0MANARMY Cảm ơn các bạn! Tôi đa đọc no. Nó rất toàn diện. @svick. Cảm ơn bạn. Bây giờ đã rõ rồi. –

3

(Chú ý: Đoán)

Int32 có một nhà điều hành chuyển đổi sang Int64 đó là những gì được gọi khi bạn làm các diễn viên đầu tiên. Object không, do đó, diễn viên thứ hai của bạn đang cố gắng truyền một đối tượng sang loại khác không phải là siêu kiểu (Int64 không kế thừa Int32).

Lý do tại sao nó hoạt động với var là hiển nhiên - trình biên dịch chỉ giúp bạn nhập int trong trường hợp đó. Với dynamic thời gian chạy thực hiện tất cả các kiểm tra cần thiết cho những gì cần phải được thực hiện trong khi thông thường trình biên dịch sẽ chỉ chèn một trong hai diễn viên hoặc gọi toán tử chuyển đổi.

5

object có loại int. Nhưng nó được coi là một đối tượng (mà là một int boxed) và một loại giá trị đóng hộp nói chung chỉ có thể được đúc thành loại cơ bản của nó (loại được đóng hộp).

Để truyền sang loại khác, trước tiên bạn phải truyền nó đến loại cơ bản. này hoạt động:

long longNumber2 = (long) (int) intNumber2; 

Lý do mà var công việc là vì trình biên dịch suy luận loại tại thời gian biên dịch. Điều đó có nghĩa là, khi bạn sử dụng var, loại intNumber2 (nếu bạn sử dụng typeof) sẽ là int. Trong khi khi bạn sử dụng object, loại sẽ là object.

Sử dụng dynamic là một quá trình hoàn toàn khác và không thể so sánh với var.Ở đây, quá trình chuyển đổi/diễn ra diễn ra trong thời gian chạy, sử dụng sự phản chiếu và thư viện DLR. Nó sẽ tự động tìm loại cơ bản, thấy rằng nó có toán tử chuyển đổi và sử dụng toán tử đó.

0

Bạn cần phải bỏ hộp thư đến cùng một loại đã được đóng hộp.

object intNumber2 = 100L; 
// or value in the long type range 
// object intNumber2 = 9223372036854775806; 

long result = (long)intNumber2; 
+1

Bạn cũng có thể thêm 'L' vào số, không cần số lớn. – Abel

+0

Thật vậy! Tôi sẽ thêm điều đó vào câu trả lời để hiển thị cả hai cách. –

1

Điều đó không hoạt động do hai loại phôi khác nhau (một chuyển đổi, hộp unboxing khác) đã được nêu trong câu trả lời ở đây. Điều có thể là một bổ sung hữu ích, là Convert.ToInt64() sẽ chuyển đổi bất kỳ thứ gì được tích hợp sẵn có thể được chuyển đổi thành dài hoặc loại của lớp thực hiện IConvertible.ToInt64(), thành một khoảng thời gian dài. Nói cách khác, nếu bạn muốn có thể truyền một đối tượng có chứa một số nguyên (có kích thước bất kỳ) thành dài, thì Convert.ToInt64() là cách để đi. Nó đắt hơn, nhưng những gì bạn đang cố gắng để làm tốn kém hơn khi đúc, và sự khác biệt là không đáng tin cậy (chỉ đủ lớn để lãng phí trong trường hợp bạn biết đối tượng phải được đóng hộp dài).

Các vấn đề liên quan