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

时间:2015-05-05 17:15:14

标签: c# generics boxing variance unboxing

在第91页的关于装箱和拆箱的 c#简介的同时,作者写道:

  
    

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

  

引用示例代码:

object [] a1 = new string [3]; //legal
object [] a2 = new int [3]; // error

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

1 个答案:

答案 0 :(得分:5)

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

这里重要的是object引用的表示int引用的表示相同。

objectint x = 10; object y = x; 之间有一个拳击转换,可以让它发挥作用:

int

......但转换涉及更多行动; CLR必须创建一个包含相关整数的对象。 object的表示int[]引用的表示相同。从数组中读取时,检查是否有必要 - 并且在执行此操作时 - 从性能角度来看会相对痛苦,因此 无效将object[]视为{ {1}}。

通用方差也是如此。这很好:

List<string> strings = new List<string>();
IEnumerable<object> objects = strings; // IEnumerable<T> is covariant in T

但这不是:

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

有关表示和身份的更多信息,请参阅Eric Lippert's blog post on the topic。 (它没有谈论方差,但它都是相关的...)