静态初始化继承的静态成员

时间:2012-10-18 11:41:23

标签: c# generics inheritance static-members

考虑这个示例代码:

public class A<T> 
{
    public static T TheT { get; set; }
}
public class B : A<string>
{
    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

3 个答案:

答案 0 :(得分:5)

  

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

基本上,你没有真的引用B。如果您查看IL,我认为您会发现您的代码实际上等同于:

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

即使您编写了B.TheT,编译器也确定确实是您所指的成员。

  

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

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

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

答案 1 :(得分:0)

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

根据MSDN参考

  

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

答案 2 :(得分:0)

在第二种情况下称为静态构造函数,它将调用实际类型的静态构造函数,而不是派生的构造函数。因此,在您的情况下,它会调用A<T> =>A<string>的{​​{1}}和 的静态ctor。

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

A

并致电

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 并调用默认的静态ctor。