静态构造函数可以在非静态构造函数之后运行。 这是编译器错误吗?
以下程序的输出是:
Non-Static Static Non-Static
这是编译器错误吗? 我期望:
Static Non-Static Non-Static
因为我认为在非静态构造函数之前总是调用静态构造函数。
我使用.net 3.5和.net 4.0在Visual Studio 2010中对此进行了测试。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace StaticConstructorBug { class Program { static void Main(string[] args) { var mc = new MyClass(); Console.ReadKey(); } } public class MyClass { public MyClass() { Console.WriteLine("Non-static"); } static MyClass() { Console.WriteLine("Static"); } public static MyClass aVar = new MyClass(); } }
见ECMA334§17.4.5.1:
17.4.5.1静态字段初始化
类声明的静态字段变量初始值设定项对应于以它们出现在类声明中的文本顺序执行的赋值序列。 如果类中存在静态构造函数(第17.11节),则在执行该静态构造函数之前立即执行静态字段初始值设定项。 否则,静态字段初始化器在第一次使用该类的静态字段之前的实现相关时间执行
具体来说:“在执行静态构造函数之前立即执行静态字段初始化程序”。
必须在静态构造函数执行之前初始化您的static MyClass aVar
(或者,至少它必须以这种方式出现)。 如果没有该静态成员,则应在任何非静态构造函数之前调用静态构造函数。
如果你仍然想要一个MyClass
单例,你可以将它放在一个容器类中并使用它来引用它,例如:
public static class MyClassSingleton { public static MyClass aVar = new MyClass(); }
它是由行public static MyClass aVar = new MyClass();
。
实际上aVar = new MyClass();
是前置到静态contrstructor。 所以你的静态构造函数:
static MyClass() { Console.WriteLine("Static"); }
更改为:
static MyClass() { aVar = new MyClass(); // this will run instance contstructor and prints "Non-Static" Console.WriteLine("Static"); }
这个public static MyClass aVar = new MyClass();
是静态构造函数的一部分。 如果你用reflection器看它,你会看到以下内容:
static MyClass() { aVar = new Program.MyClass(); Console.WriteLine("Static"); }
所以你的结果现在应该很明显了。
来自MSDN 链接 :
在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。
我猜这是因为最后一行实例的静态实例化,但根据MSDN,静态构造函数应该在第一个实例被调用之前发生。