6

考虑这个示例代码:

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

4

3 回答 3

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.
}
于 2012-10-18T11:45:17.160 回答
0

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

根据MSDN参考

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

于 2012-10-18T11:47:57.377 回答
0

在第二种情况下称为静态构造器,它将调用实际类型的静态构造器,而不是派生的构造器。因此,在您的情况下,它调用 the 的静态 ctorA<T> =>A<string>不是.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>并调用它的默认静态 ctor。

于 2012-10-18T11:49:02.627 回答