为什么不';是否所有静态构造函数都在C#中调用(即父类的构造函数)?

为什么不';是否所有静态构造函数都在C#中调用(即父类的构造函数)?,c#,static-constructor,C#,Static Constructor,我有三门课,Base,派生的和最终的派生的派生自基本的和最终的派生自派生的。这三个类都有一个静态构造函数。类派生的作为名为Setup的公共静态方法。当我调用Final.Setup时,我希望所有三个静态构造函数都会执行,但只有Derived中的一个会运行 以下是示例源代码: abstract class Base { static Base() { System.Console.WriteLine ("Base");

我有三门课,
Base
派生的
最终的
<代码>派生的派生自
基本的
最终的
派生自
派生的
。这三个类都有一个静态构造函数。类
派生的
作为名为
Setup
的公共静态方法。当我调用
Final.Setup
时,我希望所有三个静态构造函数都会执行,但只有
Derived
中的一个会运行

以下是示例源代码:

    abstract class Base
    {
        static Base()
        {
            System.Console.WriteLine ("Base");
        }
    }

    abstract class Derived : Base
    {
        static Derived()
        {
            System.Console.WriteLine ("Derived");
        }

        public static void Setup()
        {
            System.Console.WriteLine ("Setup");
        }
    }

    sealed class Final : Derived
    {
        static Final()
        {
            System.Console.WriteLine ("Final");
        }
    }
这对我来说只有部分意义。我知道调用
Final.Setup()
实际上只是
Derived.Setup()
的别名,因此跳过
Final
中的静态构造函数就足够了。但是,为什么不调用
Base
的静态构造函数


我可以通过调用
Base
的无操作静态方法或访问
Base
的虚拟静态方法来解决这个问题。但我想知道:这种明显奇怪的行为背后的原因是什么?

C#规则规定,在创建类的第一个实例或接触任何静态成员之前调用静态构造函数,因此,可能永远不会,就像您的情况一样。

静态方法属于类,没有继承。您可以调用
Final.Setup
的事实只是调用Derived.Setup的一个语法糖,因此没有引用Final的静态成员-因此不会调用静态构造函数。
基类也一样-静态成员上没有继承,因此基类在此不以任何方式参与。

在以下情况下调用静态构造函数(根据):

  • 将创建类类型的实例
  • 引用类类型的任何静态成员

作为一个例子,考虑一个类,它使用静态<代码> main < /Cult>方法开始执行:如果你有一个静态构造函数,它将在调用main方法之前被调用。 请注意,即使在执行静态构造函数之前,任何静态字段都会初始化为其默认值,然后为这些字段执行静态字段初始值设定项。只有这样,才会执行静态构造函数(cctor)


更直接地回答您的问题:静态构造函数不是继承的,并且不能直接调用它们,因此在您的场景中不会调用
Base
cctor,除非您为抽象
Base
类指定一个静态方法,并首先调用该方法,如
Base.Initialize()
,正如你已经建议的那样


关于推理,这很简单,考虑C#(在Java中这是不同的):静态方法不被继承,因此静态构造函数也不应该被继承,因为这可能会导致不必要的副作用(当没有任何引用该类时调用cctor)。

相关,而不是dup:@phresnel:在我的情况下,我从不创建任何对象,只需调用
Derived.Setup()
即可使静态构造函数在
Derived
上运行。因此,不,静态构造函数不仅仅是在创建类的实例之前调用的。@phresnel不完全是:“在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。”。这意味着,如果他访问Base中的任何内容,它的静态构造函数将被激发。@Pierre我想我的评论回答了你的问题。你从来不会对Base做任何事情,所以根据上面的规则,它的静态构造函数不会启动。@LasseSpeholt:你是对的,这也是我的结论。然而,在我看来,访问派生类中的一些静态变量相当于对基类的隐式引用。。。我仍然觉得这有点奇怪。@Pierre我倾向于同意你:)但是,如果你真的需要它,你必须正确地重构你的代码:/谢谢你的澄清。这对我来说很有意义。