Статический конструктор может работать после нестатического конструктора. Это ошибка компилятора?

Выход из следующей программы:

Non-Static
Static
Non-Static

Является ли это ошибкой компилятора? Я ожидал:

Static
Non-Static
Non-Static

потому что я думал, что статический конструктор ВСЕГДА вызывался перед нестационарным конструктором.

Я тестировал это с помощью Visual Studio 2010, используя как .net 3.5, так и .net 4.0.

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

Ответ 1

См. ECMA 334 §17.4.5.1:

17.4.5.1 Инициализация статического поля

Инициализаторы статической переменной поля объявления класса соответствуют последовательность присвоений, которые выполненных в текстовом порядке, в котором они появляются в объявлении класса. Если статический конструктор (§17.11) существует в классе, выполнение инициализаторы статического поля непосредственно перед выполнением этого статический конструктор. В противном случае статические инициализаторы полей выполняются на время, зависящее от реализации перед первым использованием статического поле этого класса

В частности: "выполнение инициализаторов статического поля происходит непосредственно перед выполнением этого статического конструктора".

Ваш static MyClass aVar должен быть инициализирован до того, как ваш статический конструктор выполнит (или, по крайней мере, должен появиться таким образом). Без этого статического члена статический конструктор должен вызываться перед любыми нестационарными конструкторами.

Если вы все еще хотите синглтон MyClass, вы можете поместить его в класс контейнера и ссылаться на него, используя это, например:

public static class MyClassSingleton
{
    public static MyClass aVar = new MyClass();
}

Ответ 2

Это вызвано линией 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

Этот public static MyClass aVar = new MyClass(); является частью вашего статического конструктора. Если вы посмотрите на него с отражателем, вы увидите следующее:

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

Итак, ваш результат должен быть очевиден.

Ответ 4

Из MSDN Ссылка:

Статический конструктор называется автоматически инициализировать класс до создания первого экземпляра или любые статические члены ссылаются.

My Guess this из-за статического экземпляра экземпляра в последней строке, но в соответствии с MSDN статический конструктор должен произойти до того, как вызывается первый экземпляр.