c#数组中的协方差被破坏
本文关键字:方差 数组 | 更新日期: 2023-09-27 18:13:33
考虑以下泛型接口ITest
具有协变类型参数T
,实现该接口的泛型类Test
,以及类A
具有子类B
:
interface ITest<out T>
{
T prop{ get;}
}
class Test<T> : ITest<T>
{
public T prop{ get {
return default(T);
}}
}
class A {
}
class B: A {
}
下面的代码编译没有错误,但是会抛出运行时异常System.ArrayTypeMismatchException
:
ITest<A>[] a = new ITest<A>[1];
a[0] = new Test<B>(); //<-- throws runtime exception
但是这段代码运行得很好:
ITest<A> r = new Test<B>();
这已经在Mono 2.10.2
(Unity3d 4.1
)上进行了测试。我认为这在某种程度上与数组中破碎的协方差有关(参见http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx)。
我不清楚为什么在分配数组槽时发生的类型检查没有考虑协方差。
我已经在VS2010中使用。net 4在Windows 7上编译和测试了给定的代码,它工作得很好,它没有给出运行时异常,因此似乎你的问题是Mono或Unity相关。
对于给定的代码,很难对问题所在做出假设。异常的确切类型和其他一些测试用例(即不使用接口的变化)将有助于缩小确切的问题,但这是Mono|Unity社区解决的问题。
至于它链接到那篇文章,这是无关的。
文章描述的是以下情况:
class A { }
class B: A { }
class C: A { }
A[] a = new B[1];
a[0] = new C(); //<-- throws ArrayTypeMismatchException
为了简化Eric在他的文章中所说的话:
a是一个变量,它可以保存继承自的任何类型的数组a .
a被赋值为B的数组,因此a是B的数组。
当用户尝试将一个新的C赋值给a的元素时,存在一个类型不匹配,因为a实际上是B的数组,因此将C赋值给a的元素相当于将一个新的C赋值给一个保存B的变量,如下所示:
B b = new C();
将A赋值为c的数组也会出现类似的问题。
然而,由于a被定义为能够保存a的数组,用户可以分配a的数组,这将允许它接受B和c的值
正因为如此,你的问题中的代码似乎与这个问题有关,但事实上,这并不是因为a被分配为ittest的数组,这意味着它应该能够存储ittest的类型,并且运行时错误被抛出源于Mono或Unity的运行时错误。