Когда в C # вызывается статический конструктор?


88

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

Ответы:


93

Когда к классу обращаются впервые.

Статические конструкторы (Руководство по программированию на C #)

Статический конструктор используется для инициализации любых статических данных или для выполнения определенного действия, которое необходимо выполнить только один раз. Он вызывается автоматически перед созданием первого экземпляра или перед ссылками на статические члены.


6
Интересно, что там написано «до создания первого экземпляра или до ссылки на статические члены». Там есть некоторая свобода действий, когда он действительно вызывается.
Тим Баррасс

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

A static constructor is used to initialize any static dataНет. Лучше использовать static initializerдля инициализации статического материала.
Юша Алеайуб

41

Это не так просто, как вы могли ожидать, несмотря на простую документацию. В статье Джона Скита http://csharpindepth.com/Articles/General/Beforefieldinit.aspx подробно рассматривается этот вопрос.

Резюме:

Статический конструктор гарантированно будет выполнен непосредственно перед первой ссылкой на член этого класса - при создании экземпляра или собственного статического метода / свойства класса.

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


Упомянутая статья теперь находится на сайте Джона Скита: csharpindepth.com/Articles/General/Beforefieldinit.aspx
Судханшу Мишра

Следующий вопрос stackoverflow.com/questions/32525628/… демонстрирует случай, когда "немедленное" поведение вполне очевидно.
Алексей Левенков

1
На самом деле у меня был случай, когда статический конструктор был вызван прямо перед тем, как основной метод консольного приложения даже начал выполняться!
HerpDerpington

19

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

Он гарантированно будет вызываться до обращения к первому статическому члену и до создания первого экземпляра. Если класс никогда не используется, вызов статического конструктора не гарантируется.


2
Когда это происходит, это не «до реализации», если эта реализация следует спецификации ECMA C #: «Выполнение статического конструктора запускается первым из следующих событий, которые происходят в домене приложения: [1] Экземпляр class создается. [2] Ссылка на любой из статических членов класса. " (Раздел 17.11, ecma-international.org/publications/standards/Ecma-334.htm )
LukeH

1
@Luke: «Точные сроки выполнения статического конструктора зависит от реализации» ondotnet.com/pub/a/dotnet/2003/07/07/staticxtor.html
Guffa

2
@Guffa: Возможно, это интерпретация автора статьи, но вы не найдете такой формулировки в версиях спецификации C # для Microsoft или ECMA / ISO.
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.