| 特性 | 欄位初始化語句 | 靜態建構函式 |
|---|---|---|
| 語法 | static int X = Compute(); | static MyClass() { X = Compute(); } |
| 執行時機 | 型別首次存取前 (CLR 保證) | 欄位初始化之後、型別首次存取前 |
| 異常處理 | 極難捕捉 (導致 TypeInitializationException) | 容易 try/catch 處理、記錄、回退 |
| 邏輯複雜度 | 僅支援單一運算式 | 支援完整陳述式、迴圈、條件判斷 |
| 參數 | 無 | 無 (CLR 自動呼叫) |
| 繼承鏈 | 基底類別先初始化 | 基底類別靜態建構函式先執行 |
public sealed class Singleton
{
// 唯一實例,readonly 確保只指派一次
private static readonly Singleton _instance = new Singleton();
// 靜態建構函式:觸發延遲初始化 (BeforeFieldInit 控制)
static Singleton() { }
private Singleton() { } // 私有建構函式防外部建立
public static Singleton Instance => _instance;
// 業務方法
public void DoWork() { }
}
原理:有靜態建構函式的類別不會被標記 BeforeFieldInit,CLR 保證在第一次存取任何靜態成員時才執行初始化,達到 Lazy 效果。.NET 4+ 也可用 Lazy<T>。
class A { public static int X = B.Y; static A() { X++; } }
class B { public static int Y = A.X; static B() { Y++; } }
// 呼叫
Debug.WriteLine(A.X); // 輸出 2
Debug.WriteLine(B.Y); // 輸出 1
A.X → 觸發 A 初始化A 欄位 X 配置空間、預設 0X = B.Y → 需存取 B.Y → 觸發 B 初始化B 欄位 Y 配置空間、預設 0Y = A.X → A 已在初始化中,**不重入**,直接讀取當前 A.X (仍為 0) → Y = 0B 靜態建構函式 → Y++ → Y = 1A 欄位初始化完成 → X = 1A 靜態建構函式 → X++ → X = 2A.X = 2, B.Y = 1Lazy<T>TypeInitializationException 重拋,保留堆疊追蹤