標籤:java 使用 strong 檔案 line new
首先我們來看看參考型別的成員初始化過程
我們來看一個例子吧
class Program { static void Main(string[] args) { DriveB d = new DriveB(); } }
class BaseA { static DisplayClass a = new DisplayClass("基類靜態成員初始化");
DisplayClass BaseA_c = new DisplayClass("基類執行個體變數BaseA_c初始化");
public BaseA() { Console.WriteLine("基類構造方法被調用"); } }
class DriveB : BaseA { static DisplayClass DriveB_b = new DisplayClass("繼承類靜態成員DriveB_b初始化");
//static BaseA DriveB_a = new BaseA();
DisplayClass DriveB_c = new DisplayClass("繼承類執行個體變數DriveB_c初始化");
public DriveB() { Console.WriteLine("繼承類構造方法被調用"); } } class DisplayClass { public DisplayClass(string diplayString) { Console.WriteLine(diplayString); Console.WriteLine(); } } 程式動行的結果是: 繼承類靜態成員DriveB_b初始化 繼承類執行個體變數DriveB_c初始化 基類靜態成員初始化 基類執行個體變數BaseA_c初始化 基類構造方法被調用 繼承類構造方法被調用
得出初始化順序結論:
1)繼承類靜態成員變數初始化 2)繼承類執行個體變數初始化 3)基類靜態靜態成員變數初始化 4)基類執行個體變數初始化 5)基類構造方法調用 6)繼承類構造方法調用。
好像結果和JAVA的有點不一樣啊, 有點混亂的感覺,搞不懂M$為什麼要讓初始化按這樣的順序執行,像JAVA那樣嚴格的從基類到衍生類別多好呀.上例的運行結果說明, 建構函式這麼這個和我們通常思路執行的順序還是有一定的差別.對於執行個體成員初始化,基本上就是以下步驟執行: 1 類的對象初始化大體順序上執行個體成員賦值到建構函式 2 成員賦值初始化按照由子類到父類的順序 3 建構函式的初始化按照由父類到子類的順序 從這裡我們有一點需要注意的是,因為成員賦值初始化是從子類到父類的,所以在子類的成員賦值初始化的過程中,不要引用父類定義的成員,因為這個時候父類成員還沒有開始初始化.需要說明一點的是C#在建立對象的第一步分配記憶體完成後會動把所有執行個體成員變數初始化成變數的預設值,例如整型就是0,參考型別就是null.然後才開始進行成員變數初始化的過程.
C#對象初始化
1. 先變數後建構函式。變數先被初始化,然後建構函式被執行
2. 先靜態化後執行個體化。當一個類被訪問時,靜態變數和建構函式最先被初始化.接著是對象的執行個體化變數和建構函式被初始化
3. 先衍生類別後基類。對於變數和靜態建構函式,派生對象在基底物件之前被初始化.比如C類派生自B類,B類派生自A類,那麼變數和靜態建構函式被初始化次序是C-B-A.
4. 除了執行個體建構函式。對於執行個體建構函式,基類建構函式在衍生類別建構函式之前執行,執行個體建構函式被執行次序是A-B-C.
5. 不要假定變數的次序。Fields依據它們在源檔案中的聲明的順序依次初始化.然而,自從程式員和工具可以隨意安排變數的聲明後,你不應該在依靠變數任何特別的次序初始化
6. 對虛方法用兩個階段的構建。避免從一個構造器調用虛方法. 如果在初始化一個對象時需要調用一些虛方法,應在完整構造該對象的地方使用兩階段的構建,並隨後調用已構造對象的初始化方法。