为什么可变性会排除协变性?
Why does mutability preclude covariance?
我正在尝试了解协变是如何工作的(一般来说,尽管我的示例将使用 C# 编写)以及泛型类型何时可以是协变的。假设我们有一个 class Animal
,子 class 是 Cat
和 Dog
。我明白为什么像 IEnumerable<T>
这样的只读类型是协变的,允许此代码编译:
IEnumerable<Animal> initialAnimalEnumerable = new List<Cat> {new Cat() };
IEnumerable<Animal> addedAnimalEnumerable = initialAnimalEnumerable.Append(new Dog());
因为enumerable的元素只能被当作类型Animal
;他们 Cats/Dogs 的具体信息丢失了。我不明白的是为什么这不适用于 List<T>
:
等可变集合
List<Animal> initialAnimalList = new List<Cat> {new Cat() }; // error CS0266: Cannot implicitly convert type 'List<Cat>' to 'List<Animal>'
initialAnimalList[0] = new Dog();
对 C# variance problem 等问题的解释似乎假设这会导致问题,因为我们正在尝试将 Dog
添加到 List<Cat>
...但是为什么它仍然被视为 List<Cat>
而不是 List<Animal>
?
您假设一个简单的情况,其中对 List<Cat>
的唯一引用是用于分配 initialAnimalList
的引用。如果你不是创建一个新的 object/reference 而是从另一个现有变量赋值怎么办:
例如:
var cats = new List<Cat> {new Cat() };
List<Animal> initialAnimalList = cats; // error CS0266
initialAnimalList[0] = new Dog();
我们还有 cats
。由于后来的一些赋值,它的类型并没有神奇地变成 List<Animal>
,并且任何以后访问 cats
的代码都有权假设它不会在那里找到 Dog
。
赋值不会更改对象的类型。
我正在尝试了解协变是如何工作的(一般来说,尽管我的示例将使用 C# 编写)以及泛型类型何时可以是协变的。假设我们有一个 class Animal
,子 class 是 Cat
和 Dog
。我明白为什么像 IEnumerable<T>
这样的只读类型是协变的,允许此代码编译:
IEnumerable<Animal> initialAnimalEnumerable = new List<Cat> {new Cat() };
IEnumerable<Animal> addedAnimalEnumerable = initialAnimalEnumerable.Append(new Dog());
因为enumerable的元素只能被当作类型Animal
;他们 Cats/Dogs 的具体信息丢失了。我不明白的是为什么这不适用于 List<T>
:
List<Animal> initialAnimalList = new List<Cat> {new Cat() }; // error CS0266: Cannot implicitly convert type 'List<Cat>' to 'List<Animal>'
initialAnimalList[0] = new Dog();
对 C# variance problem 等问题的解释似乎假设这会导致问题,因为我们正在尝试将 Dog
添加到 List<Cat>
...但是为什么它仍然被视为 List<Cat>
而不是 List<Animal>
?
您假设一个简单的情况,其中对 List<Cat>
的唯一引用是用于分配 initialAnimalList
的引用。如果你不是创建一个新的 object/reference 而是从另一个现有变量赋值怎么办:
例如:
var cats = new List<Cat> {new Cat() };
List<Animal> initialAnimalList = cats; // error CS0266
initialAnimalList[0] = new Dog();
我们还有 cats
。由于后来的一些赋值,它的类型并没有神奇地变成 List<Animal>
,并且任何以后访问 cats
的代码都有权假设它不会在那里找到 Dog
。
赋值不会更改对象的类型。