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

C# 靜態建構函式初始化靜態成員完整指南

     編輯:關於C#

靜態成員初始化兩種方式

方式語法執行時機異常處理適用場景
靜態欄位初始化器static int X = Compute();類別首次被存取前、靜態建構函式**之前****無法 try-catch**,異常會包裝為 TypeInitializationException 拋出簡單、無副作用、無異常風險的值型別/字串常數
靜態建構函式static MyClass() { X = Compute(); }類別首次被存取時、欄位初始化器**之後**✅ **可完整 try-catch**,可記錄日誌、提供預設值、避免整個應用程式崩潰複雜邏輯、IO/網路/資料庫存取、可能拋出異常、需特定順序初始化

靜態建構函式特性

  • **無參數、無存取修飾詞、不可多載** (每類別最多一個)。
  • 由 CLR 自動呼叫,**執行緒安全** (內部鎖定)。
  • 在第一次存取該類別任何靜態/實例成員、或建立實例**之前**執行。
  • 不繼承、不被衍生類別呼叫 (各類別各自執行)。

單例模式標準實作


public sealed class Singleton
{
    private static readonly Singleton _instance;
    
    static Singleton() => _instance = new Singleton(); // 靜態建構函式初始化
    
    public static Singleton Instance => _instance;
    
    private Singleton() { } // 私有建構函式防止外部 new
}

優點:簡潔、執行緒安全、Lazy (首次存取才建立)、無雙重檢查鎖定複雜度。

靜態初始化順序陷阱 (循環相依)


class A { public static int X = B.Y + 1; static A() { X++; } }
class B { public static int Y = A.X + 1; static B() { Y++; } }

// 輸出 A.X, B.Y 為何?
// 1. 存取 A.X → 初始化 A
// 2. A.X 欄位初始化器:需 B.Y → 初始化 B
// 3. B.Y 欄位初始化器:需 A.X → A 正在初始化中,**直接讀取預設值 0** → Y = 1
// 4. B 靜態建構函式:Y++ → Y = 2
// 5. 回到 A:X = B.Y(2) + 1 = 3
// 6. A 靜態建構函式:X++ → X = 4
// 結果:A.X = 4, B.Y = 2

分析三大鐵律

  1. 程式碼順序:先寫的先執行 (欄位初始化器)。
  2. 欄位初始化器 **先於** 靜態建構函式。
  3. 每個類別的初始化流程**只執行一次** (CLR 保證)。

最佳實踐建議

  1. 簡單常數:直接用欄位初始化器 static readonly int Max = 100;。
  2. 複雜/可能失敗:改用靜態建構函式包裹 try-catch,失敗時記錄日誌並設定安全預設值。
  3. 避免跨類別靜態欄位相依:若不可避免,將相依關係集中在單一類別的靜態建構函式中處理,或改用 Lazy<T> 延遲初始化打破循環。
  4. 單例:優先使用靜態建構函式或 Lazy<T> 實作。

Lazy<T> 替代方案 (更彈性)


private static readonly Lazy _resource = 
    new Lazy(() => new HeavyResource(), LazyThreadSafetyMode.ExecutionAndPublication);

public static HeavyResource Resource => _resource.Value;
  • 延遲到真正使用時才初始化 (非類別首次存取)。
  • 支援多種執行緒安全模式。
  • 可捕獲初始化異常並快取 (後續存取重擲同例外)。

掌握靜態初始化順序與異常處理,配合靜態建構函式或 Lazy<T>,即能建立健壯的靜態狀態管理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved