代码之家  ›  专栏  ›  技术社区  ›  Joe H

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

  •  11
  • Joe H  · 技术社区  · 15 年前

    以下程序的输出是:

    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 回复  |  直到 9 年前
        1
  •  11
  •   Chris Schmich    15 年前

    ECMA 334 第十七章:4.4.5.1

    17.4.5.1静态字段初始化

    静态字段变量初始值设定项 类声明对应于 分配顺序是 按文本顺序执行 它们出现在类声明中。 如果是静态构造函数(_§17.11) 存在于类中,执行 出现静态字段初始值设定项 在执行之前 静态构造函数。否则, 已执行静态字段初始值设定项 在依赖于实现的时间 在第一次使用静电 那一类的领域

    具体来说:“静态字段初始值设定项的执行发生在执行该静态构造函数之前”。

    你的 static MyClass aVar 必须在静态构造函数执行之前初始化(或者,至少,它必须以这种方式出现)。如果没有静态成员,则应在任何非静态构造函数之前调用静态构造函数。

    如果你还想要 MyClass singleton,您可以将它放在一个容器类中,并使用它引用它,例如:

    public static class MyClassSingleton
    {
        public static MyClass aVar = new MyClass();
    }
    
        2
  •  5
  •   TcKs    15 年前

    是线路引起的 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");
    }
    
        3
  •  1
  •   bitbonk    15 年前

    这个 public static MyClass aVar = new MyClass(); 是静态构造函数的一部分。如果你用反射镜观察它,你会看到以下情况:

    static MyClass()
    {
        aVar = new Program.MyClass();
        Console.WriteLine("Static");
    }
    

    所以现在你的结果应该是显而易见的。

        4
  •  0
  •   Aren    15 年前

    来自MSDN Link :

    调用静态构造函数 自动初始化类 在创建第一个实例之前 或者引用任何静态成员。

    我猜这是因为在最后一行静态实例化了实例,但是根据msdn,静态构造函数应该在调用第一个实例之前发生。