怎么U []可以转换为T []?

时间:2010-08-31 17:07:26

标签: .net arrays inheritance casting covariance

很明显,T[]数组类型不是covariant,因为T[]的元素可以通过索引设置。

然而,只要U[]来自T[]U就可以投放到T而不会受到编译器的任何投诉。

Man[] men = new[] { new Man("Aaron"), new Man("Billy"), new Man("Charlie") };
Person[] people = (Person[])men;

在上面的代码中,menpeople似乎确实拥有对同一Array个对象的引用。设置men[0] = new Man("Aidan")的效果可以在people[0]看到。同样,尝试people[0] = new Woman("Debbie")会在运行时产生ArrayTypeMismatchException

这是否意味着T[]类型实际上对每个set调用执行类型检查?如果允许以这种方式转换数组,这似乎是必要的。

我想我的问题只是:这怎么可能?我很清楚,U[]并非来自T[]。对我来说也是不清楚我是否可以定义我自己的类型以这种方式工作:实际上不变但行为协变。


*虽然 CLR 显然允许数组差异,但任何语言都可能禁止在数组类型之间进行转换。但是,似乎这种行为在VB.NET中是相同的:

Dim men = New Man() { New Man("Aaron"), New Man("Billy"), New Man("Charlie") }
Dim people = CType(men, Person())

3 个答案:

答案 0 :(得分:7)

这是数组的特殊行为,不能以任何其他类型复制。

It is generally regarded as a mistake

答案 1 :(得分:2)

这只是因为它是CLR的一部分的特殊功能。数组是自动协变的,即使技术上它们不是。编译器只需知道这一点并生成正确的类型检查。

虽然有些人认为此功能是错误的,但在类型安全集合和通用接口协方差之前进行此操作非常重要。如果没有它,您甚至无法编写一个函数来对数组进行排序。

答案 2 :(得分:1)

Eric在这里非常清楚地解释道:http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx

短简历:如果D继承B,则D []与B []协变。假设D2也继承自B,那么

B[] b = new D[10]; 
b[0] = new D1();

抛出异常。是的,这不好,但确实如此。