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

本文关键字:操作 无效 为什么 一下 能解释 | 更新日期: 2023-09-27 18:11:35

我今天正在阅读协方差和逆变,我看到一篇关于堆栈交换的文章,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不看水果碗的类型?是否因为你首先将水果碗的值设置为香蕉列表,香蕉列表协变为水果和,然后试图将苹果添加到类型实际上是List<Banana>的集合中?

感谢下面的Matt。这有助于记住您正在处理引用类型。

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

我想你错过的是,当你在你的第一个例子:

List<Fruit> fruitBowl = bunchOfBananas;

不是bunchOfBananas复制到List<Fruit>。相反,您正在创建一串香蕉的引用,该引用可用于添加任何种类的水果。

因此当你这样做时:

fruitBowl.Add(new Apple());

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