一尘不染

C#中静态类初始化的顺序是否确定?

c#

我已经做了一些搜索,并且我认为以下代码可以保证产生输出:

B.X = 7

B.X = 0

A.X = 1

A = 1, B = 0



static class B
{
    public static int X = 7;
    static B() {
        Console.WriteLine("B.X = " + X);
        X = A.X;
        Console.WriteLine("B.X = " + X);
    }
}

static class A
{
    public static int X = B.X + 1;
    static A() {
        Console.WriteLine("A.X = " + X);
    }
}

static class Program
{
    static void Main() {
        Console.WriteLine("A = {0}, B = {1}", A.X, B.X);
    }
}

我已经运行了无数次,并且始终在代码部分上方获得输出;我只是想确认它会改变吗?即使从文字上讲,班级A和班级也要B重新安排?

是否保证首次使用静态对象会触发其静态成员的初始化,然后实例化其静态构造函数?对于此程序,A.X在main中使用将触发的初始化,然后A.X依次初始化B.X,然后B()在完成初始化后A.X继续进行A()。最后,Main()将输出A.X和BX`。


阅读 292

收藏
2020-05-19

共1个答案

一尘不染

直接来自ECMA-334:

17.4.5.1:如果类中存在静态构造函数(第17.11节),则在执行该静态构造函数之前立即执行 静态字段初始化程序
否则,将在与实现相关的时间执行静态字段初始化程序 首先使用该类的静态字段。”

和:

17.11: 静态构造函数的执行由在应用程序域内发生的以下第一个事件触发:

  • 创建该类的实例。
  • 引用了该类的任何静态成员。

如果类包含开始执行的Main方法(第10.1节),则该类的静态构造函数将在调用Main方法之前执行。
如果类包含带有初始化程序的任何静态字段,则在执行静态构造函数之前,将按文本顺序执行这些初始化程序(第17.4.5节)。

因此顺序为:

  • A.X用过的,static A()所谓的。
  • A.X需要初始化,但使用B.X,即static B()所谓的。
  • B.X 需要初始化,并初始化为7。 B.X = 7
  • 的所有静态字段B均已初始化,因此static B()称为。X打印(“ 7”),然后将其设置为A.XA已经开始初始化,因此我们获得的值A.X,这是默认值(“当初始化一个类时,该类中的所有静态字段都首先被初始化为其默认值”);B.X = 0,然后打印(“ 0”)。
  • 完成初始化B,并将的值A.X设置为B.X+1A.X = 1
  • 的所有静态字段A均已初始化,因此static A()称为。A.X打印(“ 1”)。
  • 返回中Main,将打印A.X和的值B.X(“ 1”,“ 0”)。

它实际上在标准中对此进行了评论:

17.4.5: 可以在默认值状态下观察带有变量初始化器的静态字段。 但是,强烈不建议使用此样式。

2020-05-19