我目前正在处理涉及System.Reflection.Emit代码生成的问题.我想弄清楚default(SomeType)在C#中使用的地方发出什么CIL .
我从Visual Studio 11 Beta运行了一些基本实验.JustDecompile显示我以下CIL输出default(bool),default(string)以及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>
Run Code Online (Sandbox Code Playgroud)
从这一点来看,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; }
Run Code Online (Sandbox Code Playgroud)
这三种方法都生成相同的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
Run Code Online (Sandbox Code Playgroud)
题:
我可以从这一切中得出结论:C#default(SomeType)最接近CIL的......
initobj对于非原始类型(除了string?)ldc.iX.0/ ldnull/等原始类型(加string)?为什么不CreateClassNull<T>只是转换为ldnull,而是initobj转而?毕竟,ldnull被发射string(这也是一个参考类型).
Eri*_*ert 15
我可以从所有这一切的结论是C#的
default(SomeType)对应关系最为密切,以CIL的initobj非基本类型和ldc.i4.0,ldnull等基本类型?
这是一个合理的总结,但更好的思考方式是:如果C#编译器将其归类default(T)为编译时常量,则会发出常量的值.数字类型为零,bool为false,任何引用类型为null.如果它不被归类为常数,那么我们必须(1)发出一个临时变量,(2)通过其地址获取临时变量的地址,(3)initobj该临时变量和(4)确保临时变量的值是在需要时在堆栈上.
为什么不
CreateClassNull<T>只是转换为ldnull,而是转换为initobj?
好吧,让我们按照你的方式去做,看看会发生什么:
... etc
.class private auto ansi beforefieldinit P
extends [mscorlib]System.Object
{
.method private hidebysig static !!T M<class T>() cil managed
{
.maxstack 1
ldnull
ret
}
... etc
Run Code Online (Sandbox Code Playgroud)
...
D:\>peverify foo.exe
Microsoft (R) .NET Framework PE Verifier. Version 4.0.30319.17379
Copyright (c) Microsoft Corporation. All rights reserved.
[IL]: Error:
[d:\foo.exe : P::M[T]]
[offset 0x00000001]
[found Nullobjref 'NullReference']
[expected (unboxed) 'T']
Unexpected type on the stack.
1 Error(s) Verifying d:\foo.exe
Run Code Online (Sandbox Code Playgroud)
这可能就是我们不这样做的原因.