Какой статический класс инициализируется первым? - PullRequest
5 голосов
/ 01 июля 2010

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

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

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

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

Ответы [ 2 ]

10 голосов
/ 01 июля 2010

First начнет инициализацию, назначит firstArray, затем заметит, что требуется инициализация Second, чтобы получить начальное значение secondArray. * Запустится

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

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

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

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

.
0 голосов
/ 01 июля 2010

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

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

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

...