首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 靜態建構函式最佳實務:靜態成員初始化、異常處理與 Singleton 模式

     編輯:關於C語言

靜態成員初始化兩種方式比較

特性欄位初始化語句靜態建構函式
語法static int X = Compute();static MyClass() { X = Compute(); }
執行時機型別首次存取前 (CLR 保證)欄位初始化之後、型別首次存取前
異常處理極難捕捉 (導致 TypeInitializationException)容易 try/catch 處理、記錄、回退
邏輯複雜度僅支援單一運算式支援完整陳述式、迴圈、條件判斷
參數無無 (CLR 自動呼叫)
繼承鏈基底類別先初始化基底類別靜態建構函式先執行

決策建議

  • 簡單值型別/不可失敗初始化 → 欄位初始化語句 (最簡潔)
  • 複雜邏輯/外部資源/可能失敗 → 靜態建構函式 (安全、可維護)

Singleton 模式標準實作 (執行緒安全、延遲初始化)


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

執行流程推演 (三大鐵律)

  1. 程式碼順序優先:先出現的先執行
  2. 欄位初始化先於靜態建構函式
  3. 每個類別的初始化只執行一次

詳細步驟

  1. 存取 A.X → 觸發 A 初始化
  2. A 欄位 X 配置空間、預設 0
  3. 執行 X = B.Y → 需存取 B.Y → 觸發 B 初始化
  4. B 欄位 Y 配置空間、預設 0
  5. 執行 Y = A.X → A 已在初始化中,**不重入**,直接讀取當前 A.X (仍為 0) → Y = 0
  6. 執行 B 靜態建構函式 → Y++ → Y = 1
  7. 回到 A 欄位初始化完成 → X = 1
  8. 執行 A 靜態建構函式 → X++ → X = 2
  9. 結果:A.X = 2, B.Y = 1

避坑原則

  • 避免靜態欄位跨類別相依 (循環相依)
  • 若必須相依,改用屬性延遲計算或 Lazy<T>
  • 靜態建構函式中捕捉異常並包裝為 TypeInitializationException 重拋,保留堆疊追蹤
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved