在Main()之前调用了隐式静态构造函数



我有以下代码。

class Program
{
static void Main(string[] args)
{
Enterprise.Initialize("Awesome Company");
// Assertion failed when constructor of 'Reg' class is disabled.
Debug.Assert(Reg.Root == @"SoftwareAwesome Company");
}
}
public static class Enterprise
{
// Static Properties.
public static string Company
{
get;
private set;
}
// Static Methods.
public static void Initialize(string company)
{
Company = company;
}
}
public class Reg
{
public static string Root = $@"Software{Enterprise.Company}";

// ctor.
static Reg()
{
// Assertion failed when this constructor is disabled.
}
}

执行时,断言通过。但是,当Reg类的构造函数被禁用时,断言失败。仔细一看,我发现Reg类的隐式构造函数是在Main()之前调用的。如果Reg类的构造函数是显式定义的,那么它将在Main()之后被调用。

为什么隐式构造函数和显式构造函数之间存在这种差异?

这是链式静态类初始化的一个怪癖。

来自ECMA C#规格

15.5.6.2静态字段初始化

类的静态字段变量初始值设定项对应于中按文本顺序执行的分配序列它们出现在类别声明中(§15.5.6.1(分部类,";文本顺序";由指定§15.5.6.1.如果类中存在静态构造函数(§15.12(,静态字段初始化程序的执行发生在执行那个静态构造函数否则,静态字段初始化程序在第一次使用该类的静态字段

请特别注意最后一部分,这是您的问题,如果您没有静态构造函数,则无法控制字段何时初始化。在您的测试用例中,它们在您调用Enterprise.Initialize之前被初始化

简言之,你不应该依赖这些规则,它很容易出错,很可能会引发奇怪的问题。

最新更新