以下程序的输出是:
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();
}
}
答案 0 :(得分:11)
参见ECMA 334§17.4.5.1:
17.4.5.1静态字段初始化
静态字段变量初始值设定项 类声明对应于a 分配顺序 以文字顺序执行 它们出现在类声明中。 如果是静态构造函数(第17.11节) 存在于类中,执行 发生静态字段初始化程序 在执行之前 静态构造函数。否则, 执行静态字段初始值设定项 在依赖于实现的时间 在第一次使用静电之前 该类的领域
具体来说:“在执行静态构造函数之前,会立即执行静态字段初始化程序。”
您的static MyClass aVar
必须在静态构造函数执行之前初始化(或者,至少必须以这种方式出现)。如果没有该静态成员,则应在任何非静态构造函数之前调用静态构造函数。
如果您仍然想要一个MyClass
单例,可以将它放在容器类中并使用它来引用它,例如:
public static class MyClassSingleton
{
public static MyClass aVar = new MyClass();
}
答案 1 :(得分:5)
由行public static MyClass aVar = new MyClass();
引起。
实际上aVar = new MyClass();
是静态构造函数的前缀。那么你的静态构造函数:
static MyClass() {
Console.WriteLine("Static");
}
更改为:
static MyClass() {
aVar = new MyClass(); // this will run instance contstructor and prints "Non-Static"
Console.WriteLine("Static");
}
答案 2 :(得分:1)
此public static MyClass aVar = new MyClass();
是静态构造函数的一部分。如果你用反射器看它,你会看到以下内容:
static MyClass()
{
aVar = new Program.MyClass();
Console.WriteLine("Static");
}
所以你的结果现在应该是显而易见的。
答案 3 :(得分:0)
来自MSDN Link:
调用静态构造函数 自动初始化类 在创建第一个实例之前 或引用任何静态成员。
我猜这是因为最后一行实例的静态实例化,但是根据MSDN,静态构造函数应该在第一个实例被调用之前发生。