Какой статический класс инициализируется первым?
Какой статический класс инициализируется первым, если в нашем проекте есть еще один статический класс?
Например: код ниже дает нулевое исключение.
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());
}
}
Теперь, когда вы снова запускаете то же самое, это работает...