我目前正在处理一个涉及System.Reflection.Emit
代码生成的问题。我试图弄清楚在我将default(SomeType)
在 C# 中使用的地方发出什么 CIL。
我从 Visual Studio 11 Beta 运行了一些基本实验。JustDecompiledefault(bool)
向我显示了、default(string)
和的以下 CIL 输出default(int?
:
.locals init (
[0] bool V_0,
[1] string V_1,
[2] valuetype [mscorlib]System.Nullable`1<int32> V_2
)
// bool b = default(bool);
ldc.i4.0
stloc.0
// string s = default(string);
ldnull
stloc.1
// int? ni = default(int?);
ldloca.s V_2
initobj valuetype [mscorlib]System.Nullable`1<int32>
由此看来default(T)
,编译器似乎已将其解析为给定类型的最合适的 CIL。
我继续使用三种通用方法查看在更一般的情况下会发生什么:
T CreateStructDefault<T>() where T : struct { return default(T); }
T CreateClassDefault<T>() where T : class { return default(T); }
T CreateClassNull<T>() where T : class { return null; }
所有三种方法都产生相同的 CIL 方法体:
.locals init (
[0] !!T V_0,
[1] !!T V_1
)
IL_0000: nop
IL_0001: ldloca.s V_1
IL_0003: initobj !!T
IL_0009: ldloc.1
IL_000a: stloc.0
IL_000b: br.s IL_000d
IL_000d: ldloc.0
IL_000e: ret
问题:
我能从这一切中得出结论,C#default(SomeType)
最接近 CIL 的……
initobj
对于非原始类型(除了string
?)ldc.iX.0
//ldnull
等对于原始类型(加号string
)?
为什么不CreateClassNull<T>
只是翻译成ldnull
,而是翻译成initobj
?毕竟,ldnull
是为string
(这也是一个引用类型)发出的。