静态初始化inheritance的静态成员

考虑以下示例代码:

public class A { public static T TheT { get; set; } } public class B : A { static B() { TheT = "Test"; } } public class Program { public static void Main(String[] args) { Console.WriteLine(B.TheT); } } 

这里B.TheT为空。 但是,更改Main方法如下:

 public static void Main() { new B(); Console.WriteLine(B.TheT); } 

正如预期的那样, B.TheT是“测试”。 我可以理解这会强制静态构造函数运行,但为什么第一种情况不会发生这种情况呢?

我试着阅读规范,引起了我的注意(§10.12):

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

•[…]

•引用类类型的任何静态成员。

我对此的解释是,由于TheT不是B的成员,因此不强制运行B的静态构造函数。 它是否正确?

如果这是正确的,我怎么能最好让B指定如何初始化TheT

A.TheT正如预期的那样是“测试”。 我可以理解这会强制静态构造函数运行,但为什么第一种情况不会发生这种情况呢?

基本上,你还没有真正引用过B 如果你查看IL,我想你会发现你的代码实际上相当于:

 public static void Main(String[] args) { Console.WriteLine(A.TheT); } 

即使你写了B.TheT ,编译器也确定这是你的意思。

如果这是正确的,我怎么能最好让A指定如何初始化TheT?

我会尽量避免这样做,说实话……但你总是可以向B添加一个静态方法:

 public static void Initialize() { // Type initializer will be executed now. } 

静态构造函数在第一次访问之前调用,或者最迟在第一次访问时调用。 也就是说,你知道它是在第一次访问时调用的,而不是在多久之前调用的。 但是,如果不进行访问,则不会调用它。 因此,只有在调用时才能控制。

根据MSDN参考

静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作。 在创建第一个实例或引用任何静态成员之前自动调用它。

在第二种情况下称为静态构造函数,它将调用实际类型的静态构造函数,而不是派生函数的静态构造函数。 所以在你的情况下,它调用A =>A的静态ctor,而不是 A

要certificate此行为,请执行以下操作:

 public class Base { static Base() { "Base static".Dump(); } } public class Derived : Base { static Derived() { "Derived static".Dump(); } public static string temp = "Hello"; } 

并打电话

 Derived.temp.Dump(); 

你会得到:

 Derived static Hello 

这是您在代码中实际执行的操作,您访问类型A并调用它的默认静态ctor。