在 Main() 之前调用的隐式静态构造函数
Implicit static constructor called before 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 == @"Software\Awesome 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
class 的构造函数被禁用时,断言失败。仔细观察,我发现 Reg
class 的隐式构造函数在 Main()
之前被调用。如果显式定义Reg
class的构造函数,会在Main()
.
之后调用
为什么隐式构造函数和显式构造函数之间存在如此大的差异?
这是链式静态class初始化的怪癖。
15.5.6.2 Static field initialization
The static field variable initializers of a class correspond to a
sequence of assignments that are executed in the textual order in
which they appear in the class declaration (§15.5.6.1). Within a
partial class, the meaning of "textual order" is specified by
§15.5.6.1. If a static constructor (§15.12) 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.
请特别注意最后一部分,这是您的问题,如果您没有静态构造函数,您将无法控制字段何时初始化。在您的测试用例中,它们在您调用 Enterprise.Initialize
之前被初始化
总之,你不应该依赖这些规则,它很容易出错,很可能会导致奇怪的问题。
我有如下一段代码。
class Program
{
static void Main(string[] args)
{
Enterprise.Initialize("Awesome Company");
// Assertion failed when constructor of 'Reg' class is disabled.
Debug.Assert(Reg.Root == @"Software\Awesome 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
class 的构造函数被禁用时,断言失败。仔细观察,我发现 Reg
class 的隐式构造函数在 Main()
之前被调用。如果显式定义Reg
class的构造函数,会在Main()
.
为什么隐式构造函数和显式构造函数之间存在如此大的差异?
这是链式静态class初始化的怪癖。
15.5.6.2 Static field initialization
The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration (§15.5.6.1). Within a partial class, the meaning of "textual order" is specified by §15.5.6.1. If a static constructor (§15.12) 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.
请特别注意最后一部分,这是您的问题,如果您没有静态构造函数,您将无法控制字段何时初始化。在您的测试用例中,它们在您调用 Enterprise.Initialize
总之,你不应该依赖这些规则,它很容易出错,很可能会导致奇怪的问题。