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

Какой статический класс инициализируется первым, если в нашем проекте есть еще один статический класс?

Например: код ниже дает нулевое исключение.

class Program
    {
        static void Main(string[] args)
        {
            First.Write();
            Second.Write();
        }
    }
    static class First
    {
        public static int[] firstArray = new int[20];
        public static int[] secondArray = Second.secondArray;
        public static void Write()
        {
            Console.WriteLine(firstArray.ToString());
            Console.WriteLine(secondArray.ToString());
        }
    }
    static class Second
    {
        public static int[] firstArray = First.firstArray;
        public static int[] secondArray = new int[30];
        public static void Write()
        {
            Console.WriteLine(firstArray.ToString());
            Console.WriteLine(secondArray.ToString());
        }
    }

Если вы обратите внимание, вы увидите, что если First класс будет инициализировать себя так secondArray поле Second будет нулевым. Но если Second класс будет инициализировать сначала так Second учебный класс firstArray будет нулевым. Я пытаюсь сказать, что инициализация сначала дает разные результаты.

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

2 ответа

Решение

First начнут инициализировать, назначат firstArrayзатем обратите внимание, что это требует Second быть инициализированным, чтобы получить начальное значение secondArray,

Second начнёт инициализацию, а затем заметит, что требуется сначала инициализироваться. Однако CLR затем заметит, что First уже инициализируется в текущем потоке, поэтому он не будет блокироваться. SecondИнициализация будет завершена, а затем Первая инициализация будет завершена.

К счастью, поле, которое Second Потребности уже были назначены, так что "правильная вещь" происходит.

Это все очень хорошо, если First фактически начинает инициализацию первой. Однако, поскольку ни один из классов не имеет статического конструктора, возможно, что Second начнёт инициализировать сначала... потом начнёт инициализировать Firstчто бы заметить это Second уже инициализирую и беру Second.secondArrayтекущее значение (ноль) для First.secondArray, Это было бы плохо. Обратите внимание, что время инициализации для типов без статических конструкторов изменилось в.NET 4 - не с нарушением спецификации, а, возможно, с существующим нарушением кода.

Если оба First а также Second имел статические конструкторы, то First будет инициализирован первым, так как это первый класс, который Main прикасается.

Мораль ответа: не делай этого. Инициализаторы типов, которые ссылаются друг на друга, очень подвержены ошибкам. Другой пример - см. Доклад Эрика Липперта и Нила Гафтера о NDC 2010, "C# Puzzlers", который можно посмотреть на видеостранице NDC.

Я не верю, что есть какая-либо гарантия относительно того, какой статический тип инициализируется первым. Чтобы гарантировать правильную инициализацию полей, вам нужно добавить статический конструктор, например:

static class Second
{
    public static int[] firstArray = First.firstArray;
    public static int[] secondArray = new int[30];

    static Second() { }

    public static void Write()
    {
        Console.WriteLine(firstArray.ToString());
        Console.WriteLine(secondArray.ToString());
    }
}

Теперь, когда вы снова запускаете то же самое, это работает...

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