2010-10-27 46 views
14

Trong đoạn mã dưới đây:Câu hỏi về C# hiệp phương sai

interface I1 { } 
class CI1: I1 { } 

List<CI1> listOfCI1 = new List<CI1>(); 

IEnumerable<I1> enumerableOfI1 = listOfCI1; //this works 

IList<I1> listofI1 = listOfCI1; //this does not 

tôi có thể gán tôi "listOfCI1" đến một IEnumerable<I1> (do hiệp phương sai)

Nhưng tại sao tôi lại không thể gán nó vào an IList<I1>? Cho rằng vấn đề, tôi thậm chí không thể làm như sau:

List<I1> listOfI12 = listOfCI1; 

nên không hiệp phương sai cho phép tôi để gán một loại có nguồn gốc đến một loại cơ sở?

Trả lời

24

Chỉ cần đặt, IList<T> không phải là biến thể, trong khi IEnumerable<T> là. Đây là lý do tại sao ...

Giả sử IList<T> covariant. Mã bên dưới rõ ràng không an toàn cho loại ... nhưng bạn muốn lỗi ở đâu?

IList<Apple> apples = new List<Apple>(); 
IList<Fruit> fruitBasket = apples; 
fruitBasket.Add(new Banana()); // Aargh! Added a Banana to a bunch of Apples! 
Apple apple = apples[0]; // This should be okay, but wouldn't be 

Đối nhiều chi tiết về phương sai, thấy Eric Lippert của blog post series vào nó, hoặc xem video nói chuyện của tôi về sai từ NDC.

Về cơ bản, phương sai chỉ được phép ở nơi bảo đảm an toàn (và theo cách bảo quản đại diện, đó là lý do tại sao bạn không thể chuyển đổi IEnumerable<int> thành IEnumerable<object> - chuyển đổi quyền anh không bảo vệ đại diện).

+0

Btw, cuộc trò chuyện đó thật tuyệt vời. –

+0

@Arnis: Cảm ơn bạn - Tôi rất thích nó, ngay cả khi tôi không thể hiển thị video Hokey Cokey mà tôi đã ghi lại ... –

+2

Jon, nhóm BCL cũng đã thêm (IEnumerable : IEnumerable), bởi vì IEnumerable không cho phép bạn thêm bất kỳ thành viên mới (tức là bất biến của nó) làm cho nó an toàn. Nhưng mặt khác đã không thêm "ra" trên IList vì nó là mutable (làm cho nó có thể thêm một thực hiện khác nhau vào danh sách cơ bản?) –

3

số

Nếu không, sau đó bạn sẽ có thể thêm một thực hiện khác nhau của I1 vào một danh sách mà chỉ nên chứa C1 s.

1

Giao diện IList<T> không phải là biến thể.

5

tờ khai So sánh (MSDN)

public interface IEnumerable<out T> : IEnumerable 

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable 

bạn thấy rằng từ huyền diệu out? Điều này có nghĩa là hiệp phương sai được bật.

+3

Cụ thể hơn, nó có nghĩa là 'IEnumerable 'là biến thể * cho' T' *. Giao diện có thể là biến thể trong một số thông số loại nhưng không phải là các thông số khác. –