Когда в 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

Кажется, есть проблема со статическими конструкторами, на которую ответят в другом месте, но потребовалось время, чтобы переварить простое объяснение. Во всех документах и ​​пояснениях утверждается, что статический конструктор / инициализатор "гарантированно" запускается до создания экземпляра первого класса или ссылки на первое статическое поле. Проблема возникает, когда вы пытаетесь поместить статический синглтон в класс, который создает сам себя (курица / яйцо). В этом случае статический конструктор вызывается после конструктора экземпляра - и в моем случае конструктор экземпляра содержал код, который полагался на некоторые статические данные.

Статический конструктор вызывается после конструктора экземпляра?

Статический конструктор может запускаться после нестатического конструктора. Это ошибка компилятора?

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

Эмерман
источник