2010-05-20 43 views
12

Mã sau đây không biên dịch được (sử dụng VS2010) và tôi không thấy tại sao. Trình biên dịch sẽ có thể suy ra rằng List<TestClass> là 'tương thích' (xin lỗi vì thiếu một từ tốt hơn) với IEnumerable<ITest>, nhưng bằng cách nào đó nó không. Tôi đang thiếu gì ở đây?Trình biên dịch C# không nhận ra một lớp đang triển khai một giao diện


interface ITest { 
    void Test(); 
} 


class TestClass : ITest { 
    public void Test() { 
    } 
} 

class Program { 
    static void Test(IEnumerable<ITest> tests) { 
     foreach(var t in tests) { 
      Console.WriteLine(t); 
     } 
    } 
    static void Main(string[] args) { 
     var lst = new List<TestClass>(); 

     Test(lst); // fails, why? 

     Test(lst.Select(t=>t as ITest)); //success 

     Test(lst.ToArray()); // success 
    } 
} 

Trình biên dịch cho hai lỗi:

  1. Các quá tải tốt nhất phù hợp với phương pháp cho 'ConsoleApplication1.Program.Test (System.Collections.Generic.IEnumerable < ConsoleApplication2 .ITest >) 'có một số đối số không hợp lệ

  2. Đối số 1: không thể chuyển đổi từ 'System.Collections.Generic.List <ConsoleApplication2.TestClass>' thành 'System.Collections.Generic.IEnumerable <ConsoleApplication2.ITest>'

Trả lời

8

Những gì bạn đang cố gắng làm được gọi là covariance - chuyển đổi từ loại hẹp hơn (TestClass) thành loại rộng hơn (ITest). Đó là một cái gì đó bạn sẽ được sử dụng để tất cả các thời gian, nó sẽ xảy ra khi bạn chuyển đổi từ một phao đến một đôi ví dụ.

Thật không may .Net 3.5 trở xuống không hỗ trợ hiệp phương sai trong các lớp chung.

.Net 4.0 hiện hỗ trợ hiệp phương sai (và contravariance) trong generics, miễn là các lớp chung được biên dịch với từ khóa out cho các loại biến thể và in cho các loại đối ứng. IEnumerable trong .Net 4.0 được định nghĩa là covariant. Nếu bạn nhấp chuột phải vào loại IEnumerable và bấm vào nút "định nghĩa goto", bạn sẽ thấy điều này:

public interface IEnumerable<out T> : IEnumerable 

Nếu bạn đang sử dụng VS2010, bạn sẽ cần phải chắc chắn rằng dự án của bạn được nhắm mục tiêu .net 4.0. Điều này có thể được thay đổi từ các thuộc tính của dự án. Nhấp chuột phải vào dự án, chọn thuộc tính, goto tab "Ứng dụng" và kiểm tra xem "Khung mục tiêu" có thuộc về .Net 4.

MSDN has more information.

2

này phải làm với phương sai (hiệp phương sai và contravariance); hãy xem điều này post và câu trả lời của Jon Skeet

1

Kiểm tra phiên bản mục tiêu của khuôn khổ cho dự án của bạn. Mã này sẽ chỉ hoạt động trong .NET 4.

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