ModuleInitializer 是 C# 9 引入的特性,用于标记一个 static void 无参方法,在整个程序集加载后、任何类型首次访问前自动执行,适用于全局一次性初始化。
ModuleInitializer 是什么,它在什么时候执行
ModuleInitializer
是 C# 9 引入的特性,用于标记一个静态方法,在**整个程序集(assembly)被加载到 AppDomain 或托管上下文后、任何类型被首次访问前**自动运行。它不是类构造函数,不绑定到任何类型,也不支持参数或返回值,且只能是
static void
方法。
它常用于全局配置注册、日志框架初始化、DI 容器预热等“一次且仅一次”的启动逻辑。注意:它不保证在
Main
方法之前执行(取决于 JIT 和类型加载顺序),但一定早于该模块中任意其他静态成员初始化。
如何正确声明和使用 ModuleInitializer 方法
必须同时满足以下所有条件,编译器才认作有效初始化器:
方法必须是
static void
,无参数,无返回值
方法必须在
static class
中(不能是普通类或 struct)
方法必须用
[ModuleInitializer]
特性标记(需引用
System.Runtime.CompilerServices
,但通常默认可用)
同一程序集中可有多个
ModuleInitializer
方法,执行顺序由编译器决定(不保证,不可依赖)
示例:
C知道
CSDN推出的一款AI技术问答工具
下载
using System;
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+)中使用 → 编译失败,需确认项目文件含
9.0
或更高
试图在其中调用尚未 JIT 的类型静态构造器 → 可能触发意外类型加载,甚至死锁(尤其涉及跨模块依赖时)
ModuleInitializer 与 static 构造函数、Program.Main 的执行时机差异
三者本质不同,不能互相替代:
static 构造函数
:每个类型首次被引用时触发,粒度细、可控制,但无法保证全局顺序
Program.Main
:是应用入口,但此时类型可能已被 JIT 加载(比如反射扫描、属性读取),
ModuleInitializer
已执行完毕
ModuleInitializer
:发生在模块级加载阶段,比绝大多数
static
构造函数更早,但无法捕获异常(抛出异常会导致程序集加载失败,进程退出)
如果初始化逻辑需要 try/catch、日志记录或 fallback 行为,务必在方法体内自行处理——编译器不会帮你包装。