【发布时间】:2020-01-27 20:43:39
【问题描述】:
C#规范是这样写的
触发结构类型的静态构造函数的执行 由以下事件中的第一个在应用程序中发生 域名:
- 引用了结构类型的静态成员。
- 结构类型的显式声明的构造函数被调用。
在以下代码中,尽管没有发生上述事件,但仍调用了静态构造函数。
struct Notebook
{
static Notebook() => Console.WriteLine("Static Ctor");
public void Method() => Console.WriteLine("Method");
}
class Program
{
static void Main()
{
Notebook notebook;
notebook.Method();
}
}
当结构中声明的自动属性在 void Main() 中赋值时,同样适用。 在这种情况下,究竟是什么让静态构造函数被调用?
【问题讨论】:
-
来自here:在创建第一个实例或引用任何静态成员之前自动调用[A static constructor]。
-
@RobertHarvey 另一方面lang spec:structs:“结构类型的默认值(Default values)的创建不会触发静态构造函数。(这方面的一个例子是元素的初始值)数组。)”看起来需要挖掘出最新的非草案规范并仔细阅读它以确认
.Method是实际触发它的那个(即使它不是static)......可能就是这种情况没有注释说“方法不调用静态方法”) -
@Alexei:C# 5 规范(之所以选择是因为我碰巧有它)与上面提到的文本基本相同。我发现这种行为与 OP 一样令人费解,因为我的理解是,如果没有“.beforefieldinit”,运行时应该完全按照规范执行构造函数(包括静态的,并包括在结构中)。只有使用该标志(此处不存在)才允许运行时“过早”调用静态构造函数。然而,这里似乎确实如此。即使在非草案规范中,我也没有看到任何理由。
-
还有它的价值:至少早在 2010 年,Stack Overflow 上就已经注意到了这种行为:Why doesn't the CLR always call value type constructors。这个问题实际上问的是相反的问题——为什么 不是 调用的静态构造函数。但是接受的答案确实讨论了这样一个事实,即如果调用任何方法,静态构造函数将首先被调用(即按照@Alexei 之前的建议)。
标签: c# struct constructor static