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

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

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

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 было бы пустым. Я пытаюсь сказать, что то, которые инициализируют сначала, делает различные результаты.

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

5
задан CodesInChaos 12 December 2014 в 15:00
поделиться

2 ответа

Сначала начнет инициализацию, назначит firstArray , затем обратите внимание, что для получения начального значения требуется инициализация Second . of secondArray .

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

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

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

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

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

10
ответ дан 13 December 2019 в 22:01
поделиться

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

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

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

0
ответ дан 13 December 2019 в 22:01
поделиться
Другие вопросы по тегам:

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