C#中静态类初始化的顺序是确定性的吗? [英] Is the order of static class initialization in C# deterministic?

查看:10
本文介绍了C#中静态类初始化的顺序是确定性的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've done some searching and I think the following code is guaranteed to produce output:

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);
    }
}

我已经运行了很多次并且总是在代码部分上面得到输出;我只是想验证它会改变吗?即使在文本上,class A 和 class B 重新排列?

I've run this numerous times and always get the output above the code section; I just wanted to verify will it change? Even if textually, class A and class B are re-arranged?

是否保证第一次使用静态对象会触发其静态成员的初始化,然后再实例化其静态构造函数?对于这个程序,在main中使用AX会触发AX的初始化,进而初始化BX,然后B() 并在完成AX 的初始化后,将进行A().最后,Main() 将输出 A.X 和 B.X`.

Is it guaranteed that the first use of a static object will trigger the initialization of its static members, followed by instantiating its static constructor? For this program, using A.X in main will trigger the initialization of A.X, which in turn initializes B.X, then B() and after finishing the initialization of A.X, will proceed to A(). Finally, Main() will output A.X and B.X`.

推荐答案

直接来自 ECMA-334:

Straight from ECMA-334:

17.4.5.1:如果类中存在静态构造函数(第 17.11 节),则在执行该静态构造函数之前立即执行静态字段初始值设定项.否则,在第一次使用该类的静态字段之前的依赖于实现的时间执行静态字段初始值设定项."

17.4.5.1: "If a static constructor (§17.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class."

还有:

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

17.11: The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

  • 创建了一个类的实例.
  • 引用类的任何静态成员.

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

If a class contains the Main method (§10.1) in which execution begins, the static constructor for that class executes before the Main method is called. If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor (§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.X.A已经开始被初始化了,所以我们得到了AX的值,它是默认值(当一个类被初始化时,该类中的所有静态字段都首先初始化为默认值");B.X = 0,并打印(0").
  • 完成对B的初始化,A.X的值设置为B.X+1.A.X = 1.
  • A 的所有静态字段都被初始化,所以 static A() 被调用.A.X 被打印(1").
  • 回到Main,打印A.XB.X 的值(1",0").
  • A.X used, so static A() called.
  • A.X needs to be initialized, but it uses B.X, so static B() called.
  • B.X needs to be initialized, and it is initialized to 7. B.X = 7
  • All static fields of B are initialized, so static B() is called. X is printed ("7"), then it is set to A.X. A has already started being initialized, so we get the value of A.X, which is the default value ("when a class is initialized, all static fields in that class are first initialized to their default value"); B.X = 0, and is printed ("0").
  • Done initializing B, and the value of A.X is set to B.X+1. A.X = 1.
  • All static fields of A are initialized, so static A() is called. A.X is printed ("1").
  • Back in Main, the values of A.X and B.X are printed ("1", "0").

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

It actually comments upon this in the standard:

17.4.5: 可以在默认值状态下观察带有变量初始值设定项的静态字段.但是,强烈建议不要这样做.

这篇关于C#中静态类初始化的顺序是确定性的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆