为什么在调用非静态方法时会调用结构中的静态构造函数?

时间:2020-01-27 20:43:39

标签: c# struct constructor static

C#规范读取

触发结构类型的静态构造函数的执行 在应用程序中发生以下第一个事件 域:

  • 引用了struct类型的静态成员。
  • 调用显式声明的struct类型的构造函数。

在下面的代码中,尽管没有发生上述事件,但仍调用了静态构造函数。

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()中分配了值时,也是如此。 在这种情况下,究竟是什么使静态构造函数被调用?

1 个答案:

答案 0 :(得分:2)

在我看来,这种差异从根本上说是C# language specification(最新的非草稿规范,即C#5.0,已链接,但其他版本在这方面基本相同)之间的冲突。 }。

具体来说,语言规范提供了您提到的触发器,但是CLI规范包括对标记有BeforeFieldInit的类型 not 的描述(如此处所示):

何时以及什么触发此类类型初始化方法的执行的语义如下:

4.如果未标记为BeforeFieldInit,则该类型的初始化方法将在处执行(即, 被触发):
一种。首次访问该类型的任何静态字段,或者
b。首次调用该类型的任何静态方法,或者
c。首次调用该类型的任何实例或虚拟方法(如果它是一个值) 输入
d。首次调用该类型的任何构造函数。

(我的重点)

换句话说,对于运行时,规则明确是,调用任何类型的实例方法将导致调用静态构造函数(即“类型初始值设定项” )。这就是程序的行为方式。

C#规范中的语言已经存在了很长时间,从规范的早期版本一直到该语言的最新发布版本(技术上是“草稿”规范,但仍然是规定性的),这让我很难思考这种差异是一个简单的疏忽。当然,它可能是 (除非语言设计者提供了输入)。但是我认为尽管CLI的规则,语言设计者还是决定对限制进行最小化的限制(从理论上讲,C#语言可以针对其他类似的平台,可能不像CLI那样受限制)。与众不同。

毕竟,遵循C#程序的规则而不是C#规则的CLI实现对于任何人都不太可能出现问题。当程序本身不访问任何静态成员的方法被调用时,实际上不依赖静态构造函数的程序实际上应该依赖被调用,这应该是非常罕见的,并且可以说是非常糟糕的设计。