Статический конструктор может бежать за нестатическим конструктором. Действительно ли это - ошибка компилятора?

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

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();
    }
}
11
задан Kevin Panko 24 September 2015 в 14:03
поделиться

4 ответа

См. ECMA 334 §17.4.5.1:

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

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

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

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

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

public static class MyClassSingleton
{
    public static MyClass aVar = new MyClass();
}
11
ответ дан 3 December 2019 в 07:11
поделиться

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

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

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

1
ответ дан 3 December 2019 в 07:11
поделиться

Из MSDN Ссылка :

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

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

0
ответ дан 3 December 2019 в 07:11
поделиться

Это вызвано строкой 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");
}
5
ответ дан 3 December 2019 в 07:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: