让我们检查为以下通用方法生成的 MSIL 代码:
public static U BoxValue<T, U>(T value)
where T : struct, U
where U : class
{
return value;
}
看:
.method public hidebysig static !!U BoxValue<valuetype .ctor
([mscorlib]System.ValueType, !!U) T,class U>(!!T 'value') cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: unbox.any !!U
IL_000b: ret
}
但是对于上面的通用代码,更有效的 IL 表示应该是:
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: ret
从约束中可知,该值被装箱到引用类型中。Unbox.any
opcode 是完全多余的,因为在box
opcode 之后,IL 堆栈中的值已经是对 的有效引用!!U
,无需任何拆箱即可使用。
为什么 C# 3.0 编译器不使用约束元数据来生成更高效的通用代码?Unbox.any 的开销很小(只是慢了 4 到 5 倍),但为什么不在这种情况下发出更好的代码呢?