創建子對象時構造的順序
與C++相同,子類創建對象時,要創建對象的基類部分,所以需要在子類的構造函數中隱式調用父類的某個構造函數作爲創建實例過程的一部分,繼承層次鏈中的每個類在執行它自己的構造函數體之前先執行它的父類構造函數。
C#中構造順序與C++有些不同,C#首先會初始化本類中的成員,然後如果這個類有父類則再初始化父類中的成員,然後調用父類的構造函數,最後再執行本類的構造函數,多層次繼承亦是如此。下面代碼中註釋即爲執行的順序。
class A
{
public int a = 100; //3
public A() //4
{
Console.WriteLine("A");
}
}
class B :A
{
public int b = 99; //2
public B():base() //5
{
Console.WriteLine("B");
}
}
class C:B
{
public int i = 10; //1
public C():base() //6
{
Console.WriteLine("C");
}
}
class Program
{
static void Main(string[] args)
{
C c = new C();
}
}
不能在構造函數中調用虛方法
在構造函數中調用虛方法時極不推薦的,在執行基類的構造函數時,基類的虛方法會調用派生類的覆寫方法,但這是在執行派生類的構造函數方法體之前,因此調用會在派生類沒有完全初始化之前傳遞到派生類。
子類構造函數中需調用父類的構造函數(base)
默認情況下,在構造對象時,子類的構造函數會自動調用父類的無參構造函數,但構造函數可以重載,所以父類可能有一個以上的構造函數,如果希望子類使用一個指定的父類構造函數而不是無參構造函數,則必須在構造函數初始化語句中指定它。
此語句由關鍵字base和要調用的基類構造函數的參數列表組成。
使用當前類中其他構造函數作爲構造函數初始化語句(this)
另外一種形式的構造函數初始化語句可以讓構造過程使用當前類中其他的構造函數。
class A
{
public A(int i):this(i,"aaaaa") { } //此構造函數調用到倆個參數的構造函數
public A() { }
public A(int i, string s)
{
Console.WriteLine(i);
Console.WriteLine(s);
}
}
class Program
{
static void Main(string[] args)
{
A a = new A(100); //100 aaaa
}
}
這種用法很有用的一種情況是,一個類有好幾個構造函數,並且它們都需要在對象構造的過程開始時執行一些公共代碼,對於這種情況,可以把公共代碼提取出來作爲一個構造函數,被其他所有的構造函數作爲構造函數初始化語句使用,由於減少了重複的代碼,實際上這也是推薦的做法。