泛型只支持引用转换,不支持装箱转换

Generics supports only reference conversions not boxing conversions

在阅读 c# in a nutshell 第 91 页关于装箱和拆箱的内容时,作者写道:

Boxing conversions are crucial in providing a,unified type system. The system is not perfect, however we will see in Generics that variance with arrays and generics supports only **reference conversions ** and not **boxing conversions **

并引用示例代码:

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

谁能解释一下作者试图表达的意思以及为什么第一行合法而第二行不合法?

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

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

intobject 之间有一个 装箱转换 ,这使得这个工作:

int x = 10;
object y = x;

...但是转换涉及更多操作; CLR 必须创建一个包含相关整数的对象。 int 的表示与 object 引用的表示 不同 。从数组读取时检查是否有必要 - 并边做边做 - 会相对痛苦(从性能角度来看),因此 not 有效处理 int[]作为 object[].

泛型方差也是如此。这很好:

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。 (不是很讲方差,但都是相关的。。。)