有人能解释为什么这个操作无效吗?

时间:2013-05-01 13:02:37

标签: c# .net covariance contravariance invariants

今天我正在阅读关于协方差和逆变的文章,我遇到了一个关于堆栈交换的帖子,其中Jon Skeet解释了班级的不变性。他用了一个水果的例子,为什么在这个级别允许协方差会是一件坏事:

//Bad
List<Banana> bunchOfBananas = new List<Banana>();
// This would be valid if List<T> were covariant in T
List<Fruit> fruitBowl = bunchOfBananas;
fruitBowl.Add(new Apple());
Banana banana = bunchOfBananas[0];

那么,如何使用Fruit列表来添加从Fruit继承的类的实例呢?例如:

//Good
List<Fruit> fruitBowl = new List<Fruit>();
fruitBowl.Add(new Apple());
fruitBowl.Add(new Banana());

我过去做过这个,它总是表现得像预期的那样。为什么CLR看不到fruitBowl的类型?是因为你首先将fruitBowl的值设置为香蕉列表,它与Fruit列表协变,然后然后尝试将Apple添加到类型为{{1}的集合中}?

感谢下面的马特。它有助于记住您正在处理引用类型。永远地投下这个。

1 个答案:

答案 0 :(得分:1)

我认为你缺少的是当你第一个例子时:

List<Fruit> fruitBowl = bunchOfBananas;

bunchOfBananas的副本复制到List<Fruit>。相反,您正在创建对一堆香蕉的引用,并且该引用可用于添加任何类型的水果。

因此当你这样做时:

fruitBowl.Add(new Apple());

你不会将苹果添加到水果列表中;你要在List<Banana> bunchOfBananas添加一个苹果,这显然是一件坏事。