2011-11-10 43 views
8

thể trùng lặp:
Foreach can throw an InvalidCastException?Tại sao trình biên dịch cho phép phiếu này?

Hãy xem xét các khối mã sau đây

public class Base 
{ 
} 

public class DerivedLeft : Base 
{ 
} 

public class DerivedRight : Base 
{ 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Base> list = new List<Base> { new DerivedLeft(), new DerivedRight() }; 
     foreach (DerivedLeft dl in list) 
     { 
      Console.WriteLine(dl.ToString()); 
     } 
    } 
} 

Thông báo các diễn viên từ cơ sở để DerivedLeft trong bản Tuyên Bố foreach. Điều này biên dịch tốt (Visual Studio 2010), mà không có bất kỳ lỗi hoặc thậm chí cảnh báo. Rõ ràng, trên vòng lặp thứ hai, chúng ta sẽ nhận được một InvalidCastException. Nếu tôi được hỏi một câu hỏi về phản ứng của trình biên dịch với mã như vậy, tôi sẽ không nghi ngờ gì, trình biên dịch đó sẽ không để điều này không được chú ý và tạo ra ít nhất một cảnh báo. Nhưng rõ ràng là không. Vì vậy, tại sao trình biên dịch cho phép điều này thông qua?

Trả lời

2

Bởi vì danh sách là loại List<Base> và biến dl trong vòng lặp foreach là loại DerivedLeft trong đó có cơ sở như lớp cơ sở. Vì vậy, có thể hoạt động trong thời gian chạy, nhưng không phải . Trình biên dịch không kiểm tra việc khởi tạo danh sách của bạn.

+0

Tôi nghĩ rằng trình biên dịch không kiểm tra khởi .... ví dụ. nếu tôi đặt MyOtherClass ở đó để có một ngoại lệ thời gian biên dịch –

+0

@RoyiNamir: Có, trình biên dịch sẽ kiểm tra nếu khởi tạo là chính xác, nhưng nó không kiểm tra xem các phần tử phù hợp có ở trong nó khi anh ta đạt đến vòng lặp foreach hay không. – Fischermaen

+0

đúng ............ –

0

Mong các trình biên dịch để nâng cao một lỗi về vấn đề này cũng giống như mong đợi nó để nâng cao một lỗi về điều này:

Base b = new DerivedRight(); 
DerivedLeft d = (DerivedLeft)b; 
+0

trong thực tế trình biên dịch sẽ nâng cao một lỗi về điều này, vì bạn đã không cung cấp tên biến cho DerivedLeft :) – Trogvar

+0

true ......... :) – nogola

+0

Trong sự công bằng, các diễn viên ngầm tham gia vào 'foreach' không rõ ràng, trừ khi người ta đã mã hóa với 'C#' cho .NET1.0 hoặc 1.1, trong đó thiếu các generics có nghĩa là nó sẽ khó xử hơn nhiều nếu không có diễn viên ngầm, như mọi 'foreach' mà không 't đối phó với 'đối tượng' sẽ cần một. –

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