简体   繁体   English

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

[英]Static initialization of inherited static member

Consider this example code: 考虑这个示例代码:

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);
    }
}

Here B.TheT is null. 这里B.TheT为空。 However, changing the Main method like this: 但是,更改Main方法如下:

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

B.TheT is "Test", as expected. B.TheT是预期的“测试”。 I can understand that this forces the static constructor to run, but why does this not happen for the first case? 我可以理解这会强制静态构造函数运行,但为什么第一种情况不会发生这种情况呢?

I tried reading the spec, and this caught my attention (§10.12): 我试着阅读规范,引起了我的注意(§10.12):

[...] The execution of a static constructor is triggered by the first of the following events to occur within an application domain: [...]静态构造函数的执行由应用程序域中发生的以下第一个事件触发:

• [...] •[...]

• Any of the static members of the class type are referenced. •引用类类型的任何静态成员。

My interpretation of this is that since TheT is not a member of B , the static constructor of B is not forced to be run. 我对此的解释是,由于TheT是不是成员B ,静态构造函数B不强制运行。 Is this correct? 它是否正确?

If that is correct, how would I best let B specify how to initialize TheT ? 如果这是正确的,我怎么能最好让B指定如何初始化TheT

A.TheT is "Test", as expected. A.TheT是“测试”,正如预期的那样。 I can understand that this forces the static constructor to run, but why does this not happen for the first case? 我可以理解这会强制静态构造函数运行,但为什么第一种情况不会发生这种情况呢?

Basically, you haven't really referenced B . 基本上,你还没有真正引用过B If you look in the IL, I think you'll find that your code was actually equivalent to: 如果你查看IL,我想你会发现你的代码实际上相当于:

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

The compiler worked out that that's really the member you meant, even though you wrote B.TheT . 编译器的工作指出,这是真的你的意思是会员,即使你写B.TheT

If that is correct, how would I best let A specify how to initialize TheT? 如果这是正确的,我怎么能最好让A指定如何初始化TheT?

I would try to avoid doing this to start with, to be honest... but you could always just add a static method to B : 我会尽量避免这样做,说实话......但你总是可以向B添加一个静态方法:

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

Static constructor is called before the first access or at the latest when the first access is made. 静态构造函数在第一次访问之前调用,或者最迟在第一次访问时调用。 Ie you know it has been called when first access is made but not how long before. 也就是说,你知道它是在第一次访问时调用的,但不是在多久之前调用的。 However, if no access is made it won't be called. 但是,如果不进行访问,则不会调用它。 So you cannot control when only if it s called. 因此,只有当它被调用时你才能控制它。

As per MSDN reference 根据MSDN参考

A static constructor is used to initialize any static data, or to perform a particular action that needs performed once only. 静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作。 It is called automatically before the first instance is created or any static members are referenced. 在创建第一个实例或引用任何静态成员之前自动调用它。

In second case called static contructor and it will call the actual types' static contructor, and not that one of derived one. 在第二种情况下称为静态构造函数,它将调用实际类型的静态构造函数,而不是派生函数的静态构造函数。 So in your case it calls the static ctor of the A<T> =>A<string> and not of A . 所以在你的情况下,它调用A<T> =>A<string>的静态ctor,而不是 A

To prove this behaviour just do the following: 要证明此行为,请执行以下操作:

public class Base {

    static Base() {
      "Base static".Dump(); 
    }
}

public class Derived : Base {

    static Derived() {
      "Derived static".Dump(); 
    }

    public static string temp = "Hello";
}

and call 并打电话

Derived.temp.Dump();

You will get: 你会得到:

Derived static
Hello

This is what you actually do in your code, you acess derived type A<string> and it's default static ctor is called. 这是你在你的代码实际上做的,你接取派生类型A<string>和它的默认构造函数静态调用。

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

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