差異在於編譯器未產生對基類的多重呼叫,也未複製實例變數到每個建構函式。基類建構函式僅在最後一個建構函式中呼叫。關鍵限制:你不能同時包含更多建構函式預置方法。在類別中,你可以用 this() 委派給另一建構函式,或用 base() 呼叫基類建構函式,但不能兩者並用。
仍不清楚建構函式預置方法?考慮唯讀常數:物件名稱在生命週期不應改變,故設為 readonly。若使用輔助函式建構物件會導致編譯錯誤:
public class MyClass
{
private readonly string _name;
public MyClass() { commonConstructor(0, ""); }
public MyClass(int initialCount) { commonConstructor(initialCount, ""); }
public MyClass(int initialCount, string Name) { commonConstructor(initialCount, Name); }
private void commonConstructor(int count, string name)
{
_coll = (count > 0) ? new ArrayList(count) : new ArrayList();
_name = name; // ERROR: 唯讀欄位只能在建構函式中指派
}
}
C++ 程式設計師會將 _name 放在每個建構函式或輔助函式中。C# 建構函式預置方法提供優雅替代方案:幾乎所有非瑣碎類別包含多個建構函式,其工作皆為初始化所有成員。使用 C# 建構函式鏈結產生這些常規演算法,只寫一次、只執行一次。
這是關於物件建構的最後一個原則,複習型別建構時的完整事件順序:
後續同類型實例從第 5 步開始(類別初始化只執行一次)。第 6、7 步經優化,編譯器在建構函式預置方法上移除重複指令。
C# 編譯器保證所有事物以相同方法初始化。至少確保型別建立時,物件佔用的所有記憶體已歸零(靜態與實例成員同)。目標:確保你期望的初始化程式碼只執行一次。簡單資源用初始化器,複雜邏輯成員用建構函式。盡可能委派呼叫其他建構函式以減少重複。