Статический конструктор вызывается после конструктора экземпляра?

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

Проблема: Руководство по программированию на C# гласит:

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

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

Давайте рассмотрим пример кода:

using System;

public class Test
{
    static public Test test = new Test();
    static Test()
    {
        Console.WriteLine("static Test()");
    }
    public Test()
    {
        Console.WriteLine("new Test()");
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Main() started");
        Console.WriteLine("Test.test = " + Test.test);
        Console.WriteLine("Main() finished");
    }
}

Это выводит:

Основное () началось
новый тест ()
статический тест ()
Test.test = Test
Основное () закончено

Таким образом, мы видим, что конструктор экземпляра завершает работу (и, таким образом, создается экземпляр) до запуска статического конструктора. Разве это не противоречит Руководству? Может быть, инициализация статических полей считается неявной частью статического конструктора?

1 ответ

Решение

Встроенные инициализаторы для static поля запускаются до явного static конструктор.

Компилятор превращает ваш класс во что-то вроде этого:

public class Test {
    .cctor {    //Class constructor
        Test.test = new Test();                //Inline field initializer
        Console.WriteLine("static Test()");    //Explicit static ctor
    }
    .ctor { ... }    //Instance constructor
}

Обратите внимание, что это не зависит от порядка объявления.

Чтобы процитировать спецификации:

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

Другие вопросы по тегам