Запустив этот простой код:
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
выполняется статический ctor
42
Это означает, что сначала вызывается метод InitService, затем инициализируется статическое поле MyClassWithStatic, а затем вызывается статический конструктор (фактически, глядя на это в ILSpy и IlDasm, мы можем видеть, что инициализация статических полей происходит в начале кктор)
На данный момент ничего интересного нет, все логично, но когда я убираю статический конструктор 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.
-Теперь мне абсолютно известна эта страница:
Пользователь не может контролировать, когда в программе выполняется статический конструктор.
И я также знаю, что в статическом конструкторе есть много вещей, которые вы не должны делать. Но, к сожалению, мне приходится иметь дело с кодом, в котором эта часть находится вне моего контроля, и разница, которую я описал, имеет огромное значение. (И я также рассмотрел много вопросов SO, связанных с C# cctor..)
(И Вопрос №3:) Так не является ли все, что я описал, немного проблематичным?