標題比較抽象,所以我寫了一個Demo來說明問題:
公共A類
{
公共 A()
{
Console.WriteLine("A的建構子被呼叫");
}
}
公共B類:A
{
私有 X x = new X(); //初始化器
}
公開課X
{
公共 X()
{
Console.WriteLine("X的建構子呼叫");
}
}
靜態無效主(字串[]參數)
{
B b = 新 B();
}
在呼叫子類別的建構函數之前,會先呼叫基底類別的建構函數,那麼初始化器和基底類別的建構函數到底誰先執行呢?
因為初始化程式碼會在建構函式中的程式碼執行,所以我過去錯誤的想法是:
公共B類:A
{
私有 X x = new X(); //初始化器
}
等價於:
公共B類:A
{
私人××;
公共 B()
{
x=新X();
}
}
所以我也錯誤的認為基底類別的建構子是在子類別的初始化器執行之前的,上面的Demo執行的結果正好相反,是:
X的建構函式調用
A的建構函式被調用
這表示子類別的建構器先執行了,讓我們來看看產生的建構子的IL程式碼:
公開B級:A級
{
私人××;
公共 B()
{
x = 新 X();
}
}
產生的建構函數的IL程式碼是這樣的:
.method public hidebysig 特殊名稱 rtspecialname
實例 void .ctor() cil 管理
{
// 代碼大小 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001:呼叫實例 void ConsoleApplication1.Program/A::.ctor()
IL_0006:無
IL_0007:無
IL_0008:ldarg.0
IL_0009: newobj 實例 void ConsoleApplication1.Program/X::.ctor()
IL_000e: stfld 類別 ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_0013: 沒有
IL_0014:返回
} // 方法 B::.ctor 結束
從程式碼中可以看出是先呼叫基底類別的建構子的!
公共B類:A
{
私有 X x = new X();
}
產生的建構函數的IL程式碼是這樣的:
.method public hidebysig 特殊名稱 rtspecialname
實例 void .ctor() cil 管理
{
// 代碼大小 19 (0x13)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj 實例 void ConsoleApplication1.Program/X::.ctor()
IL_0006: stfld 類別 ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
IL_000b:ldarg.0
IL_000c:呼叫實例 void ConsoleApplication1.Program/A::.ctor()
IL_0011:無
IL_0012:返回
} // 方法 B::.ctor 結束
可以看出是先呼叫初始化器的程式碼,然後再呼叫基底類別的構造函數!
C#編譯器為什麼這樣設計,我也沒想到太合理的原因,大家有什麼看法呢?
請大家多多指教啊!
-