首先我們來看看引用類型的成員初始化過程
我們來看一個例子吧
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. 對虛方法用兩個階段的構建。避免從一個構造器調用虛方法. 如果在初始化一個對象時需要調用一些虛方法,應在完整構造該對象的地方使用兩階段的構建,並隨后調用已構造對象的初始化方法。