.ctor,.cctor 以及 對象的構造過程.ctor:簡述:構造函數,在類被實例化時,它會被自動調用。當C#的類被編譯后,在IL代碼中會出現一個名為.ctor的方法,它就是我們的構造函數,對應C#中的構造函數。且看下面的代碼:
public
class
Class1
{ private string name; private int age; }
類Class1中沒有顯示的構造函數,只有兩字段,現在用ILDasm.exe打開編譯后生成的exe文件,會看到:
可以看到這里有個.ctor,我們沒有定義構造函數,但這里卻出現了.ctor,這就說明了: 當沒有顯示定義構造函數時,會自動生成一個構造函數,它沒有參數,沒有返回值。 那我們來看看這個.ctor都干了什么吧,雙擊.ctor打開,在彈出的窗口中可以找到下面的幾行代碼: IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: ret
public
class
Class1
{ private string name = "Lin"; private int age; }
再用ILDasm打開生成的exe文件,打開.ctor,里面有這么幾行: IL_0001: ldstr "Lin" IL_0006: stfld string ConsoleApplication1.Class1::name IL_000b: ldarg.0 IL_000c: call instance void [mscorlib]System.Object::.ctor() IL_0011: nop
public
class
Class1
{ private string name = "Lin"; private int age;![]() public Class1(string name, int age) { this.name = name; this.age = age; } }
再用ILDasm打開exe時,會發現有了點變化: IL_0000: ldarg.0 IL_0001: ldstr "Lin" IL_0006: stfld string ConsoleApplication1.Class1::name IL_000b: ldarg.0 IL_000c: call instance void [mscorlib]System.Object::.ctor() IL_0011: nop IL_0012: nop IL_0013: ldarg.0 IL_0014: ldarg.1 IL_0015: stfld string ConsoleApplication1.Class1::name IL_001a: ldarg.0 IL_001b: ldarg.2 IL_001c: stfld int32 ConsoleApplication1.Class1::age IL_0021: nop .cctor簡述:類型初始化器,是一個靜態方法,無參數無返回值,不能直接調用,最多只有一個我們現在先給剛才的代碼加上一個靜態字段:
public
class
Class1
{ private string name = "Lin"; public static int count = 50; private int age;![]() public Class1(string name, int age) { this.name = name; this.age = age; } }
再來打開ILDasm來看看:
發現這里多了一個.cctor,它就是類型初始化器,打開它,會看到其中有一句: IL_0000: ldc.i4.s 50 IL_0002: stsfld int32 ConsoleApplication1.Class1::count
public
class
Class1
{ private string name = "Lin"; public static int count = 50; private int age;![]() static Class1() { count = 100; }![]() public Class1(string name, int age) { this.name = name; this.age = age; } }
再來看看現在ILDasm下的.cctor,其中有幾行: IL_0000: ldc.i4.s 50 IL_0002: stsfld int32 ConsoleApplication1.Class1::count IL_0007: nop IL_0008: ldc.i4.s 100 IL_000a: stsfld int32 ConsoleApplication1.Class1::count 可以看到: 在繼承中對象構造過程看下面這段程序:
public
class
A
{ public int x = 1; public A() { m1(); } public void m1() { } }
![]()
public
class
B : A
{ public int y = 2; public static string sb = "B"; public B() { m2(); } public void m2() { } }
![]()
public
class
C : B
{ public int z = 3; public static string sc = "C"; public C() { m3(); } public void m3() { } }
編譯后用ILDasm打開生成的exe文件:
可以看到三者都有一個.ctor,B、C中有.cctor,而A沒有,打開B,C的.cctor,可以看到它們都負責初始化自己的靜態字段,現在主要來看它們的.ctor。 先看類C的.ctor: IL_0001: ldc.i4.3 IL_0002: stfld int32 ConsoleApplication1.C::z IL_0007: ldarg.0 IL_0008: call instance void ConsoleApplication1.B::.ctor() IL_000d: nop IL_000e: nop IL_000f: ldarg.0 IL_0010: call instance void ConsoleApplication1.C::m3() 在C被實例化時,它最先初始化在聲明時同時賦值的字段(非靜態),此處是將3賦給z,然后它會調用其基類的.ctor(),然后再調用自己的實例方法m3(),值得注意的是,在執行顯式定義的構造方法體中的代碼前,會先調用其基類的構造方法(創建基類的實例)。 再來看類B的.ctor(): IL_0001: ldc.i4.2 IL_0002: stfld int32 ConsoleApplication1.B::y IL_0007: ldarg.0 IL_0008: call instance void ConsoleApplication1.A::.ctor() IL_000d: nop IL_000e: nop IL_000f: ldarg.0 IL_0010: call instance void ConsoleApplication1.B::m2() 那A的.ctor()就不再看了,可以猜到它一定是在做這樣的事: 1、 將1賦給實例的x字段; 2、 調用基類System.Object的構造方法.ctor來創建基類的實例; 3、 調用實例方法m1(); 總結1、.ctor是構造方法; 參考資料1、《Essential .NET》 Volume 1 原文:http://www.cnblogs.com/mouhong-lin/archive/2008/05/18/1201747.html |


}
}