Статическое поле инициализируется позже, когда класс имеет статический конструктор
Запустив этот простой код:
class Program
{
class MyClassWithStatic
{
public static int Number = SomeService.GetData();
static MyClassWithStatic()
{
Console.WriteLine("static ctor runs");
}
}
class SomeService
{
public static int GetData()
{
Console.WriteLine("GetDataRuns");
return 42;
}
}
static void Main(string[] args)
{
InitService();
var value = MyClassWithStatic.Number;
Console.WriteLine(value);
}
private static void InitService()
{
Console.WriteLine("InitServiceRuns");
}
}
Вывод на моей машине такой:
InitServiceRuns
GetDataRuns
статический ход
42
Это означает, что сначала вызывается метод InitService, затем инициализируется статическое поле MyClassWithStatic, а затем вызывается статический конструктор (на самом деле, глядя на это в ILSpy и IlDasm, мы видим, что инициализация статических полей происходит в начале cctor)
В этом нет ничего интересного, все имеет смысл, но когда я удаляю статический конструктор MyClassWithStatic (таким образом MyClassWithStatic становится этим, а все остальное остается прежним)
class MyClassWithStatic
{
public static int Number = SomeService.GetData();
}
Вывод такой:
GetDataRuns
InitServiceRuns
42
Это означает, что при удалении статического конструктора статические поля инициализируются ранее. Поскольку инициализация является частью статического конструктора (я говорю об этом, рассматривая его с помощью ildasm), эффект в основном заключается в том, что статический конструктор вызывается ранее.
Итак, вот вопрос:
Может кто-нибудь объяснить это поведение? В чем может быть причина этого?
Есть ли что-то еще, что может измениться при вызове статического конструктора? (Например, присоединение профилировщика или запуск его в IIS и т. Д.) (Я сравнил отладку, режим выпуска, x86, x64 и все показывают одинаковое поведение)
Некоторые общие вещи:
-Это было в консольном приложении .NET 4.6. Я также перешел на .NET 2 (должен работать с другим clr, и поведение такое же, это не имеет никакого значения)
-Я также пробовал это с ядром .NET: как с, так и без cctor, сначала вызывается метод InitService.
-Теперь я абсолютно в курсеэта страница:
Пользователь не может контролировать, когда статический конструктор выполняется в программе.
И я также знаю, что в статическом конструкторе есть много вещей, которые вы не должны делать. Но, к сожалению, мне приходится иметь дело с кодом, где эта часть находится вне моего контроля, и разница, которую я описал, имеет огромное значение. (И я также прошел через много вопросов, связанных с C # cctor ...)
(И Вопрос №3 :) Так не все ли это, что я описал, немного проблематично?