C# Net9的模塊初始化器(Module Initializer)
Module Initializer 是為了讓庫/框架在程序集加載時,以 “CLR 保證的、只運行一次的、不依賴類型訪問的” 方式執行初始化邏輯,從而避免靜態構造函數的副作用和性能問題。
為什么需要 Module Initializer?
1. 靜態構造函數的問題
- 觸發時機不確定:CLR 保證在第一次訪問類型前調用靜態構造函數,但 你無法精確控制它什么時候運行。
- 性能開銷:CLR 對靜態構造函數的類型會加鎖,防止并發初始化,這會帶來性能損耗。
- 不能跨類型共享初始化邏輯:每個有靜態構造函數的類都要單獨處理,無法集中初始化。
2. 模塊初始化器的優勢
- 只運行一次:在程序集加載時 由 CLR 自動調用一次,不依賴任何類型訪問。
- 無類型訪問開銷:不需要觸發某個類型的靜態構造函數來“順便”初始化。
- AOT 兼容的初始化邏邏輯
using System.Runtime.CompilerServices; class Program { static void Main() { Console.WriteLine("Main"); } } class Init { [ModuleInitializer] public static void Initialize() { Console.WriteLine("Module Initializer runs before Main!"); } }
輸出:
Module Initializer runs before Main!
Main
在 NativeAOT 場景里,所有必須在運行時“反射”才能完成的事情都必須提前在編譯期做完。Module Initializer 就是“把編譯期算好的東西在程序一啟動就塞進運行時”的唯一可靠入口——它跑在 任何用戶代碼、任何泛型實例化、任何反射調用之前,而且 不需要觸發某個類型的靜態構造,因此不會引入 AOT 禁止的動態路徑。
NativeAOT 的底線是 “運行時不能做任何‘發現’工作”。所有發現必須在編譯期完成,而 發現結果塞進運行時的唯一零成本窗口就是 Module Initializer;
因此只要你在 AOT 模式下看到“編譯期源生成器 + 運行時注冊表/函數指針/緩存” 這種組合,背后幾乎一定藏著一個 [ModuleInitializer]——它已經成了 AOT 生態的隱形基礎設施。

浙公網安備 33010602011771號