昨天在回答SO問題時,我注意到如果使用Object Initializer初始化一個對象,編譯器會創建一個額外的局部變量。使用對象初始值設定項時,爲什麼編譯器會生成額外的局部變量?
考慮下面的C#3.0的代碼,在釋放模式在VS2008編譯:
public class Class1
{
public string Foo { get; set; }
}
public class Class2
{
public string Foo { get; set; }
}
public class TestHarness
{
static void Main(string[] args)
{
Class1 class1 = new Class1();
class1.Foo = "fooBar";
Class2 class2 =
new Class2
{
Foo = "fooBar2"
};
Console.WriteLine(class1.Foo);
Console.WriteLine(class2.Foo);
}
}
使用反射器,我們可以檢查爲主要方法的代碼:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] class ClassLibrary1.Class1 class1,
[1] class ClassLibrary1.Class2 class2,
[2] class ClassLibrary1.Class2 <>g__initLocal0)
L_0000: newobj instance void ClassLibrary1.Class1::.ctor()
L_0005: stloc.0
L_0006: ldloc.0
L_0007: ldstr "fooBar"
L_000c: callvirt instance void ClassLibrary1.Class1::set_Foo(string)
L_0011: newobj instance void ClassLibrary1.Class2::.ctor()
L_0016: stloc.2
L_0017: ldloc.2
L_0018: ldstr "fooBar2"
L_001d: callvirt instance void ClassLibrary1.Class2::set_Foo(string)
L_0022: ldloc.2
L_0023: stloc.1
L_0024: ldloc.0
L_0025: callvirt instance string ClassLibrary1.Class1::get_Foo()
L_002a: call void [mscorlib]System.Console::WriteLine(string)
L_002f: ldloc.1
L_0030: callvirt instance string ClassLibrary1.Class2::get_Foo()
L_0035: call void [mscorlib]System.Console::WriteLine(string)
L_003a: ret
}
在這裏,我們可以看到編譯器已生成對Class2
(class2
和<>g__initLocal0
)的實例的兩個引用,但是隻有一個對Class1
(class1
)的實例的引用。現在
,我不是很熟悉,IL,但它看起來像它的實例<>g__initLocal0
,設置class2 = <>g__initLocal0
之前。
爲什麼會發生這種情況?
它是否遵循那麼使用對象初始化器(即使它非常輕微)時會有性能開銷?
+1,很好的例子 – Tenner 2009-11-05 17:36:32