静态构造函数可以在非静态构造函数之后运行。这是编译器错误吗?

时间:2010-05-27 22:58:51

标签: c# static-constructor

以下程序的输出是:

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

4 个答案:

答案 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,静态构造函数应该在第一个实例被调用之前发生。