2011-07-16 40 views
16

Xem xét đoạn mã.Hiệp phương sai chung và đối nghịch

IList<String> obj=new List<string>(); 
IEnumerable<Object> obj1 = obj; 

Nhưng nếu tôi viết ICollection<Object> obj2 = obj; nó sẽ cho tôi một lỗi thời gian biên dịch.

Không thể chuyển đổi hoàn toàn loại 'System.Collections.Generic.IList<string>' thành 'System.Collections.Generic.ICollection<object>'.

Tại sao hành vi này từ List<T> cụ cả IEnumerable<T>ICollection<T> và cũng IList<T> được định nghĩa là

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable 
{ 
    T this[int index] { get; set; } 
    int IndexOf(T item); 
    void Insert(int index, T item); 
    void RemoveAt(int index); 
} 

Trả lời

20

ICollection<T> không hiệp biến trên tham số kiểu, trong khi IEnumerable<T> là. Nếu bạn xem tờ khai của họ (ICollection, IEnumerable), bạn có thể thấy rằng IEnumerable<T> sử dụng từ khóa out trên T, trong khi ICollection<T> thì không. Điều này có ý nghĩa nếu bạn nghĩ về điều đó, vì hiệp phương sai (nói gần) là an toàn khi giao diện sẽ chỉ được sử dụng để đọc các đối tượng (và do đó từ khóa out). IEnumerable<T> đáp ứng rõ ràng tiêu chí đó, trong khi ICollection<T> hoàn toàn ngược lại.

Như một ví dụ về những gì có thể đi sai (sử dụng ví dụ của bạn):

IList<String> obj = new List<string>(); // Legal, of course 
ICollection<Object> obj1 = obj;   // Illegal, but let's see what happens 
obj1.Add(new NonStringObject());  // That's not a string being stored in a List<string> 

Hãy nhớ rằng: hiệp phương sai là không giống như thừa kế. Chỉ vì hai lớp hoặc giao diện chia sẻ một quan hệ thừa kế không có nghĩa là các tham số kiểu của chúng có cùng đặc điểm phương sai.

+0

@ dlev.Bạn có thể giải thích thêm một chút nữa không. Điều này làm cho 'IEnumerable 'covariant và' ICollection 'thì không. –

+0

@Ashely Chỉ cập nhật câu trả lời của tôi với thông tin đó. – dlev

4

Chìa khóa ở đây là liệu bộ sưu tập có thể sửa đổi được hay không. IEnumerable<T> là bộ sưu tập chỉ đọc của T s, trong khi ICollection<T> hỗ trợ Add. Một bộ sưu tập sửa đổi không thể hiệp biến, bởi vì:

IList<String> obj = new List<String>(); 
ICollection<Object> obj1 = obj; 
obj1.Add(new Elephant()); 

này sẽ typecheck, vì (có lẽ) Elephant là một lớp con của Object. Nhưng bây giờ obj, là một List<string> có một phần tử cuối cùng là một phần tử cuối cùng của nó, rõ ràng là một điều xấu.

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