静态初始化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
的静态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。