C#静态构造函数的用法(附带实例)
在 C# 程序中,一个类型只能定义一个静态构造函数,名称必须和类型同名,且没有参数:
运行时将在类型使用之前调用静态构造函数,以下两种行为可以触发静态构造函数执行:
从 C# 9 开始,除了静态构造函数之外,我们还可以定义模块初始化器,它在每个程序集中只会执行一次(当程序集第一次加载时)。定义模块初始化器需要编写一个静态方法,并在该方法上应用 [ModuleInitializer] 特性:
静态字段初始化器按照字段声明的先后顺序运行。在下面例子中,X 初始化为 0,而 Y 初始化为 3:
class Test { static Test() { Console.WriteLine("Type Initialized"); } }注意,每个类型的静态构造函数只会执行一次,而不是每个实例执行一次。
运行时将在类型使用之前调用静态构造函数,以下两种行为可以触发静态构造函数执行:
- 实例化类型;
- 访问类型的静态成员;
如果静态构造函数抛出了未处理的异常,则该类型在整个应用程序生命周期内都是不可用的。静态构造函数只支持 unsafe 和 extern 这两个修饰符。
从 C# 9 开始,除了静态构造函数之外,我们还可以定义模块初始化器,它在每个程序集中只会执行一次(当程序集第一次加载时)。定义模块初始化器需要编写一个静态方法,并在该方法上应用 [ModuleInitializer] 特性:
[System.Runtime.CompilerServices.ModuleInitializer] internal static void InitAssembly() { ... }
C#静态构造函数和字段初始化顺序
静态模块初始化器会在调用静态构造函数前运行。如果类型没有静态构造函数,则字段会在类型被使用之前或者在运行时的任意更早时间进行初始化。静态字段初始化器按照字段声明的先后顺序运行。在下面例子中,X 初始化为 0,而 Y 初始化为 3:
class Foo { public static int X = Y; // 0 public static int Y = 3; // 3 }如果我们交换两个字段初始化顺序,则两个字段都将初始化为 3。以下示例会先输出 0 后输出 3,因为字段初始化器在 X 初始化为 3 之前创建了 Foo 的实例:
Console.WriteLine(Foo.X); // 3 class Foo { public static Foo Instance = new Foo(); public static int X = 3; Foo() => Console.WriteLine(X); // 0 }如果交换上面代码中加粗的两行,则两个字段上下两次都输出 3。