<p>ModuleInitializer 是 C# 9 引入的特性,用于标记一个 static void 无参方法,在整个程序集加载后、任何类型首次访问前自动执行,适用于全局一次性初始化。</p>

ModuleInitializer 是什么,它在什么时候执行
ModuleInitializer 是 C# 9 引入的特性,用于标记一个静态方法,在**整个程序集(assembly)被加载到 AppDomain 或托管上下文后、任何类型被首次访问前**自动运行。它不是类构造函数,不绑定到任何类型,也不支持参数或返回值,且只能是 static void 方法。
它常用于全局配置注册、日志框架初始化、DI 容器预热等“一次且仅一次”的启动逻辑。注意:它不保证在 Main 方法之前执行(取决于 JIT 和类型加载顺序),但一定早于该模块中任意其他静态成员初始化。
如何正确声明和使用 ModuleInitializer 方法
必须同时满足以下所有条件,编译器才认作有效初始化器:
- 方法必须是
static void,无参数,无返回值 - 方法必须在
static class中(不能是普通类或 struct) - 方法必须用
[ModuleInitializer]特性标记(需引用System.Runtime.CompilerServices,但通常默认可用) - 同一程序集中可有多个
ModuleInitializer方法,执行顺序由编译器决定(不保证,不可依赖)
示例:
using System;
<p>static class Startup
{
[ModuleInitializer]
public static void Initialize()
{
Console.WriteLine("模块已加载,正在初始化...");
// 比如:ServiceCollectionExtensions.AddMyServices(...)
}
}ModuleInitializer 常见错误和限制
很多看似合理写法会直接编译失败或静默失效:
- 把
[ModuleInitializer]放在非static class里 → 编译错误:CS8893: A module initializer must be in a static class - 方法带参数、返回值、
async、private或非static→ 编译错误:CS8892: A module initializer must be a static method with no parameters and no return value - 在 .NET Standard 2.0 或旧版 SDK(未启用 C# 9+)中使用 → 编译失败,需确认项目文件含
<LangVersion>9.0</LangVersion>或更高 - 试图在其中调用尚未 JIT 的类型静态构造器 → 可能触发意外类型加载,甚至死锁(尤其涉及跨模块依赖时)
ModuleInitializer 与 static 构造函数、Program.Main 的执行时机差异
三者本质不同,不能互相替代:
-
static 构造函数:每个类型首次被引用时触发,粒度细、可控制,但无法保证全局顺序 -
Program.Main:是应用入口,但此时类型可能已被 JIT 加载(比如反射扫描、属性读取),ModuleInitializer已执行完毕 -
ModuleInitializer:发生在模块级加载阶段,比绝大多数static构造函数更早,但无法捕获异常(抛出异常会导致程序集加载失败,进程退出)
如果初始化逻辑需要 try/catch、日志记录或 fallback 行为,务必在方法体内自行处理——编译器不会帮你包装。










