协方差和与C#数组的对比

wjm*_*wjm 7 .net c# oop covariance contravariance

在阅读维基百科关于协方差和逆变的文章的一部分时,我遇到了以下粗体句:

首先考虑数组类型构造函数:从Animal我们可以创建类型的类型Animal[]("动物数组").我们应该把它视为

  • 协变:a Cat[]是aAnimal[]
  • 逆变:a Animal[]是aCat[]
  • 或两者(不变)?

如果我们希望避免类型错误,并且数组支持读取和写入元素,那么只有第三种选择是安全的.显然,不是每一个都Animal[]可以被视为一个Cat[],因为从阵列读取的客户端将期望一个Cat,但是Animal[]可能包含例如a Dog.所以逆变规则并不安全.

相反,一个Cat[]不能被视为一个Animal[].它总是可以Dog放入一个Animal[].对于协变数组,这不能保证是安全的,因为后备存储实际上可能是一组猫.所以协变规则也不安全 - 数组构造函数应该是不变的.请注意,这只是可变数组的问题; 协变规则对于不可变(只读)数组是安全的.

我理解这个概念; 我只是想要一个如何在C#中"无法保证安全" 的例子.

Jon*_*eet 18

在编译时不安全.换句话说,这些代码在语言规则中是合法的,但在执行时失败,没有任何明确的强制转换来给出"这可能会失败"的大警告信号.CLR确保在执行时只有有效写入成功.例如:

string[] strings = new string[1];
object[] objects = strings;
objects[0] = new object();
Run Code Online (Sandbox Code Playgroud)

这将ArrayTypeMismatchException在执行时抛出异常().替代方案是在执行时允许它,此时strings[0]将是对非字符串对象的引用,这显然是坏的.

另见最近的博客文章: