Статический конструктор может запускаться после нестатического конструктора. Это ошибка компилятора? - PullRequest
11 голосов
/ 28 мая 2010

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

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

Ответы [ 4 ]

11 голосов
/ 28 мая 2010

См. 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();
}
5 голосов
/ 28 мая 2010

Вызывается строкой 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");
}
1 голос
/ 28 мая 2010

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

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

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

0 голосов
/ 28 мая 2010

От MSDN Ссылка :

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

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

...