C# 為純物件導向語言,物件生命週期包含配置記憶體、初始化、使用、銷毀四階段。理解初始化順序對撰寫高品質程式碼至關重要,特別是繼承體系中靜態/實例成員與建構函式的交互行為。本文以 C# 2.0 為例,原則適用於所有符合 CLS 規範的語言。
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 初始化");
DisplayClass DriveB_c = new DisplayClass("衍生類實例變數 DriveB_c 初始化");
public DriveB() { Console.WriteLine("衍生類建構函式被呼叫"); }
}
class DisplayClass
{
public DisplayClass(string msg) { Console.WriteLine(msg); Console.WriteLine(); }
}
衍生類靜態成員 DriveB_b 初始化 衍生類實例變數 DriveB_c 初始化 基類靜態成員初始化 基類實例變數 BaseA_c 初始化 基類建構函式被呼叫 衍生類建構函式被呼叫
初始化順序總結:
C# 靜態成員僅在首次存取該類別時初始化(BeforeFieldInit 語意),優點:減少啟動記憶體佔用、加快組件載入速度。
class A { public static int X; static A() { X = B.Y + 1; } }
class B { public static int Y = A.X + 1; static B() { } static void Main() { Console.WriteLine($"X={A.X}, Y={B.Y}"); } }
輸出: X=1, Y=2
Main 在 B 中,先執行 B 的靜態欄位初始化:Y = A.X + 1。A.X 觸發 A 靜態建構函式:X = B.Y + 1。B.Y 尚未完成賦值(仍為預設值 0),故 X = 1。A 靜態建構函式結束,回到 B.Y 賦值:Y = A.X + 1 = 2。結論:靜態初始化包含欄位宣告賦值與靜態建構函式,僅執行一次,循環參考時依賴預設值。