c# - C# 数组中的协方差被破坏?

标签 c# mono covariance type-mismatch

考虑以下带有协变类型参数 T 的泛型接口(interface) ITest,实现该接口(interface)的泛型类 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 )。

我不清楚为什么分配数组槽时发生的类型检查没有考虑协方差。

最佳答案

我已经在 Windows 7 上使用 .Net 4 编译并测试了 VS2010 中的给定代码,它工作正常,它没有给出运行时异常,因此您的问题似乎与 Mono 或 Unity 相关。

对于给定的代码,很难对问题所在做出假设。 异常的确切类型和一些其他测试用例(即不使用接口(interface)的变体)将有助于缩小确切问题的范围,但这是 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被分配为ITest的数组,意味着它应该能够存储ITest的类型并且抛出的运行时错误源于 Mono 或 Unity 运行时中的错误。

关于c# - C# 数组中的协方差被破坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16542915/

相关文章:

c - 从另一个进程中加载​​的 dylib 读取数据字段

c# - Gtk# 中是否有文件夹浏览器小部件?

c# - 从 Func<object,string> 到 Func<string,string> 的转换有效,但到 Func<int,string> 失败

c# - C#中的接口(interface)继承

scala - 为什么 Spark RDD 在 T 中是不变的?

c# - 当需要将数组复制回主机时如何避免同步?

c# - 如何使用网站集检查用户的权限?

c# - Identity asp.net core 3.0 - 找不到IdentityDbContext

c# - 静态变量在 ASP.NET 页面中的什么地方起作用?

c# - 在 Mono 2.10 中使用表值参数 (SqlDbType.Structured)