Коли в C # викликається статичний конструктор?


88

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

Відповіді:


93

Коли клас відвідується вперше.

Статичні конструктори (Посібник з програмування на C #)

Статичний конструктор використовується для ініціалізації будь-яких статичних даних або для виконання певної дії, яку потрібно виконати лише один раз. Він викликається автоматично перед створенням першого екземпляра або посиланням на будь-які статичні члени.


6
Цікаво, що там сказано "до створення першого екземпляра або посилання на будь-які статичні члени". Там є деяка свобода, коли це насправді викликається.
Тім Баррас

6
@TimBarrass з - за деякі інші вимоги специфікації виходить, що «до того » насправді «безпосередньо перед» - дивіться статтю Джона Скиту , згадувану в іншому відповіді - stackoverflow.com/a/1437372/477420
Олексій Левенко

A static constructor is used to initialize any static dataНЕМАЄ. Краще використовувати static initializerдля ініціалізації статичних речей.
Yousha Aleayoub

41

Це не так просто, як можна було б очікувати, незважаючи на пряму документацію. Стаття Джона Скіта http://csharpindepth.com/Articles/General/Beforefieldinit.aspx детально розглядає це питання.

Короткий зміст:

Статичний конструктор гарантовано виконується безпосередньо перед першим посиланням на члена цього класу - або створення екземпляра, або власний статичний метод / властивість класу.

Зверніть увагу, що статичні ініціалізатори (якщо немає статичного конструктора) гарантовано виконуються в будь-який час до першого посилання на певне поле.


Згадана стаття зараз знаходиться на сайті Джона Скіта: csharpindepth.com/Articles/General/Beforefieldinit.aspx
Sudhanshu Mishra

Наступне запитання stackoverflow.com/questions/32525628/… демонструє випадок, коли "негайна" поведінка є цілком очевидною.
Олексій Левенков

1
Я насправді мав випадок, коли статичний конструктор був викликаний безпосередньо перед тим, як метод Main консольного додатка навіть почав виконуватися!
HerpDerpington 16.03.18

19

Статичний конструктор викликається до того, як ви використовуєте що-небудь у класі, але саме тоді це залежить від реалізації.

Гарантований виклик до доступу до першого статичного члена та до створення першого екземпляра. Якщо клас ніколи не використовується, статичний конструктор взагалі не гарантується.


2
Коли це трапляється, це не "до реалізації", якщо ця реалізація відповідає специфікації ECMA C #: "Виконання статичного конструктора запускається першою з наступних подій, що відбувається в домені програми: [1] Екземпляр клас створений. [2] Будь-який із статичних членів класу є посиланням. " (Розділ 17.11, ecma-international.org/publications/standards/Ecma-334.htm )
LukeH

1
@Luke: "Точний час виконання статичного конструктора залежить від реалізації" ondotnet.com/pub/a/dotnet/2003/07/07/staticxtor.html
Гуффа,

2
@Guffa: Це може бути інтерпретація автора статті, але ви не знайдете цього формулювання у версіях Microsoft # або ECMA / ISO специфікації C #.
LukeH

1

У разі виклику статичного методу з батьківського класу, статичний конструктор не буде викликаний, хоча це явно вказано. Ось приклад конструктора b не викликається, якщо b.methoda () викликається.

static void Main(string[] args)
{
    b.methoda();
}

class a
{
    public static void methoda()
    {
        //using initialized method data
    }
}

class b : a
{
    static b()
    {
        //some initialization
    }
}    

1

Здається, існує помилка зі статичними конструкторами, на яку дають відповіді в іншому місці, але потрібно деякий час, щоб перетворити її на просте пояснення. Усі документи та пояснення стверджують, що статичний конструктор / ініціалізатори "гарантовано" запускатиметься перед створенням першого класу або посиланням на перше статичне поле. Зачіпка з’являється, коли ви намагаєтесь додати статичний синглтон до класу, який створює екземпляр самого себе (курка / яйце). У цьому випадку статичний конструктор закінчується викликом після конструктора екземпляра - і в моєму випадку конструктор екземпляра містив код, який покладався на деякі статичні дані.

Статичний конструктор, що викликається після конструктора екземпляра?

Статичний конструктор може працювати за нестатичним конструктором. Це помилка компілятора?

(для мене відповіддю було помістити синглтон в окремий клас або ініціалізувати вручну статичні дані в конструкторі екземпляра до того, як це буде потрібно)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.