根据文件:
静态构造函数用于初始化任何静态数据,或执行仅需要执行一次的特定操作。在创建第一个实例之前自动调用 ,或者引用任何静态成员。
但是我在stackoverflow帖子中看到了以下来自C#规范的引用:
如果类中存在静态构造函数(第10.12节),则执行静态字段初始值设定项会立即先前执行该静态构造函数。
这是矛盾的,我不明白先来的是什么,静态构造函数或静态成员初始化。
答案 0 :(得分:3)
您提到的两个陈述都是真实的并且彼此同步。我不确定你为什么认为它们是矛盾的。
执行顺序如下:
- 带有初始化程序的静态字段。
- 静态构造函数。
醇>
以上是根据你的第二个陈述。第一个陈述只提到这些行动何时执行,即:
- 创建了该类的第一个实例。
- 引用任何静态成员。
醇>
实际上,上述条件可以作为静态构造函数的保证,静态构造函数将被执行,静态构造函数将在任何两个发生之前被调用(语句1)。
C# specification明确提到:
类的静态构造函数在给定的时间内最多执行一次 应用领域。触发静态构造函数的执行 在应用程序中发生以下第一个事件 domain:创建类的实例。任何静态成员 该类的引用。如果类包含Main方法 (第3.1节)执行开始,静态构造函数为 该类在调用Main方法之前执行。如果是一个班级 包含具有初始化程序的任何静态字段,这些初始化程序是 在执行静态之前立即以文本顺序执行 构造
只需添加,因为您已突出显示 -
在创建第一个实例或引用任何静态成员之前。
这意味着即使在创建该类的实例之前,也可以引用类的静态成员。因此,即使在这种情况下,也会在访问静态成员之前调用静态构造函数。
如果你在他的回答中看到DavidG的代码,即使该类没有被实例化,但是正在引用其中一个静态成员,静态字段初始化也会在此之前发生,然后是静态构造函数执行。
示例:
public static class Test
{
public static int i = 10;
public static int j = new Func<int>(() => {
Console.WriteLine("Static field initializer called."); return 20;
})();
static Test()
{
Console.WriteLine("Static Constructor called.");
}
}
现在执行:
Console.WriteLine(Test.i);
您将获得以下输出:
调用静态字段初始值设定项。
静态构造函数调用。
10
答案 1 :(得分:2)
考虑这个课程:
public static class TestStatic
{
public static int SomeValue = GetValue();
static TestStatic()
{
Console.WriteLine("Constructor");
}
}
这种支持方法:
public static int GetValue()
{
Console.WriteLine("GetValue");
return 5;
}
如果您运行此代码:
Console.WriteLine(TestStatic.SomeValue);
您将获得的输出是:
GetValue
Constructor
5
所以你可以看到你发布的两个陈述都是正确的。在引用静态成员(SomeValue
)之前调用构造函数,并在构造函数之前调用静态字段初始化程序。
答案 2 :(得分:0)
这种行为(以及它的设计)的原因是静态字段的初始化实际上是作为静态构造函数的一部分发生的。编译器为静态构造函数逻辑预先设置了静态字段初始化器的所有表达式。