字段启动器(静态或非静态)和构造函数(静态与否)哪个首先运行



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

  1. Field Initializers在构造函数之前运行。
  2. Staticfield Initializers调用staticconstructor之前执行(这仍然与点 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);
}
}

此代码打印 0,然后打印 3 !这怎么可能?当我们通过执行 Foo.X 使用 Foo 时,在构造函数之前调用两个前初始值设定项(到目前为止还可以),当

public static Foo Instance = new Foo();

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

我真的无法遵循这方面的逻辑,请向我澄清。

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

  1. 当 Foo.X : 执行:公共静态 Foo 实例 = 新 Foo();
  2. 在调用打印的构造函数("In constructor: " + X)之前,公共静态 int X = 3;应该执行,但碰巧构造函数先触发,不是应该先完成字段运行吗?我的意思是,即使在跳入创建新的Foo实例时,也必须首先运行字段。
  3. 从最后两点开始,我希望打印 3 然后打印 3

如果一个类型没有静态构造函数,字段初始值设定项将在使用类型之前执行(据我了解:不是被实例化而是被使用)

不一定。

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

从 C# 5 规范部分 10.5.5.1:

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

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

编辑:似乎您对构造函数调用感到困惑。Foo已经被初始化 - 构造函数调用不会改变这一点,也没有"第二次初始化"。构造函数正常调用,打印"0",然后返回。然后X分配的值为 3。

Foo()

构造函数不是静态构造函数,因此它不会像case 3那样首先运行。

因此,首先从上到下初始化字段。

static Foo首次初始化时,它被执行,这就是打印0,然后当X初始化时,这就是通过System.Console.WriteLine()调用打印的内容。

最新更新