为什么最后一行不允许?
因为double是值类型而object是引用类型;协方差仅在两种类型都是引用类型时才起作用。
这是因为 double 是一种不是从对象派生的值类型,因此协方差不起作用吗?
不。Double 确实派生自 object。所有值类型都源自对象。
现在你应该问的问题是:
为什么协方差不能用于转换IEnumerable<double>
to IEnumerable<object>
?
Because 谁打拳击?从 double 到 object 的转换必须box双。假设您有一个电话IEnumerator<object>.Current
这“确实”是对实现的调用IEnumerator<double>.Current
。调用者期望返回一个对象。被调用者返回一个双精度值。执行装箱指令的代码在哪里,该指令将返回的双精度值转换为IEnumerator<double>.Current
变成盒装双打?
It is nowhere,这就是地方,这就是为什么这种转换是非法的。致电给Current
将在计算堆栈上放置一个八字节双精度数,而使用者将期望在计算堆栈上对装箱双精度数进行四字节引用,因此使用者将因堆栈不对齐而崩溃并严重死亡以及对无效内存的引用。
如果您想要框出的代码execute那么它必须是written在某个时候,你就是那个写它的人。最简单的方法是使用Cast<T>
扩展方法:
IEnumerable<object> objects2 = doubleenumerable.Cast<object>();
现在,您调用一个包含装箱指令的辅助方法,该装箱指令将双精度数从八字节双精度数转换为引用。
更新:评论者指出,我已经提出了这个问题——也就是说,我通过预设存在一种机制来回答问题,该机制可以像解决原始问题所需的那样努力地解决问题。如何实施Cast<T>
能否解决知道是否装箱的问题?
它的工作原理就像这个草图。请注意,参数类型是not通用的:
public static IEnumerable<T> Cast<T>(this IEnumerable sequence)
{
if (sequence == null) throw ...
if (sequence is IEnumerable<T>)
return sequence as IEnumerable<T>;
return ReallyCast<T>(sequence);
}
private static IEnumerable<T> ReallyCast<T>(IEnumerable sequence)
{
foreach(object item in sequence)
yield return (T)item;
}
确定从对象到 T 的转换是拆箱转换还是引用转换的责任被推迟到运行时。抖动知道 T 是引用类型还是值类型。 99% 的情况下它当然是引用类型。