次のジェネリックメソッド用に生成された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
制約から、値が参照型にボックス化されていることがわかります。オペコードの後、ILスタックの値はすでにへの有効な参照になり、ボックスを解除せずに使用できるUnbox.any
ため、オペコードは完全に冗長です。box
!!U
C#3.0コンパイラが制約メタデータを使用してより効率的なジェネリックコードを出力しないのはなぜですか?Unbox.anyは小さなオーバーヘッド(わずか4倍から5倍遅い)を与えますが、このシナリオでより良いコードを出力しないのはなぜですか?