繁体   English   中英

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

[英]Static initialization of inherited static member

考虑这个示例代码:

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

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.
}

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

根据MSDN参考

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

在第二种情况下称为静态构造函数,它将调用实际类型的静态构造函数,而不是派生函数的静态构造函数。 所以在你的情况下,它调用A<T> =>A<string>的静态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

这是你在你的代码实际上做的,你接取派生类型A<string>和它的默认构造函数静态调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM