字段Initilizers(静态或非静态)和构造函数(静态或非静态)首先运行

Aym*_*udi 5 .net c# constructor initializer visual-studio

根据我读到的内容,我不清楚某些事情:

  1. Field Initializers 在构造函数之前运行.
  2. Static field Initializers在调用之前执行static constructor(仍与第1点兼容).
  3. 如果一个类型没有静态构造函数,field Initializers将在使用的类型之前执行(据我所知:没有实例化,而是被使用)

这个例子解释了:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Foo.X);
        Console.ReadLine();
    }
}

class Foo
{
    public static Foo Instance = new Foo();
    public static int X = 3;

    Foo()
    {
        Console.WriteLine("In constructor: " + X);
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码打印0,然后3!怎么可能呢?当我们通过Foo.X使用Foo时,会在构造函数之前调用两个第一个初始化器(到目前为止还可以),

public static Foo Instance = new Foo();
Run Code Online (Sandbox Code Playgroud)

执行它应该在调用构造函数(第1点)之前运行它自己的2个初始化程序,而它首先运行构造函数并打印X作为默认值为0.

我不能真正遵循这个逻辑,请向我澄清.

编辑:我期望发生的事情:

  1. 当Foo.X:执行:public static Foo Instance = new Foo();
  2. 在调用打印的构造函数之前("在构造函数中:"+ X),public static int X = 3; 应该执行,但是构造函数首先触发,是不是认为字段完全先运行?我的意思是即使在跳入内部创建新的Foo实例时,也必须先运行字段.
  3. 从最后两点我打算打印3然后打3

Jon*_*eet 5

如果类型没有静态构造函数,则字段Initializers将在使用的类型之前执行(据我所知:没有实例化,而是被使用)

不必要.

如果没有静态构造函数,则静态字段初始值设定项将在首次使用静态字段之前的某个时间执行 - 但静态字段初始值设定项不必在创建任何实例之前执行.

从C#5规范部分10.5.5.1:

类的静态字段变量初始值设定项对应于以它们出现在类声明中的文本顺序执行的赋值序列.如果类中存在静态构造函数(第10.12节),则在执行该静态构造函数之前立即执行静态字段初始值设定项.否则,静态字段初始化器在第一次使用该类的静态字段之前的实现相关时间执行.

但在你的情况下,你只是看到当Foo为了初始化而调用构造函数时Instance,X仍然是0,因为它尚未被赋值.字段初始Instance值设定项以文本顺序执行,因此之前会赋值X.就这么简单-它不是静态字段和实例字段之间的时序的问题,因为你没有得到任何实例字段.

编辑:似乎你被构造函数调用弄糊涂了.Foo已经被初始化 - 构造函数调用不会改变它,并且没有"第二次初始化".正常调用构造函数,打印"0"然后返回.然后 X赋值为3.