为什么可变性会排除协变性?

Why does mutability preclude covariance?

我正在尝试了解协变是如何工作的(一般来说,尽管我的示例将使用 C# 编写)以及泛型类型何时可以是协变的。假设我们有一个 class Animal,子 class 是 CatDog。我明白为什么像 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

赋值不会更改对象的类型。