泛型仅支持引用转换而不支持装箱转换

Ehs*_*jad 2 c# generics boxing unboxing variance

虽然在第91页上简单地阅读关于装箱和拆箱的c#,但作者写道:

拳击转换对于提供统一类型系统至关重要.该系统并不完美,但我们将在泛型中看到,与数组和泛型的差异仅支持**引用转换**而不支持**装箱转换**

并引用示例代码:

object [] a1 = new string [3]; //legal
object [] a2 = new int [3]; // error
Run Code Online (Sandbox Code Playgroud)

有人可以解释作者试图提供的内容以及为什么第一行是合法的而第二行不是?

Jon*_*eet 5

好吧,在和之间有一个引用转换,因为每个字符串引用都可以被视为对象引用.这可以透明地完成,根本不对值进行修改.这就是为什么阵列差异可以廉价地完成的原因 - 无论如何都是为了读取.从一个值(在编译时已知)读取(实际上是在执行时),基本上是免费的 - 您可以读取该值,并将其视为参考.写作更痛苦 - 每次写入都必须检查您正在编写的值是否与您尝试存储它的数组真正兼容.stringobjectobject[]string[]objectobject[]

这里最重要的是,表示一的string基准是一样的的表现object的参考.

有一个装箱转换之间intobject它可以让这项工作:

int x = 10;
object y = x;
Run Code Online (Sandbox Code Playgroud)

......但转换涉及更多行动; CLR必须创建一个包含相关整数的对象.的表示int一样的的表示object参考.检查是否这是必要的-而且做起来,当您去-从数组中读取数据时会比较痛苦的(从性能角度看),所以它不能有效治疗的int[]作为object[].

通用方差也是如此.这可以:

List<string> strings = new List<string>();
IEnumerable<object> objects = strings; // IEnumerable<T> is covariant in T
Run Code Online (Sandbox Code Playgroud)

但这不是:

List<int> ints = new List<int>();
IEnumerable<object> objects = ints; // Covariance doesn't apply here
Run Code Online (Sandbox Code Playgroud)

有关表示和身份的更多信息,请参阅Eric Lippert关于该主题的博客文章.(它没有非常谈论方差,但它都是相关的......)