Kiedy konstruktor statyczny jest wywoływany w języku C #?

88

Kiedy mam klasę zawierającą konstruktor statyczny, czy ten konstruktor jest wywoływany, gdy zestaw zawierający klasę jest ładowany po raz pierwszy, czy po trafieniu pierwszego odwołania do tej klasy?

Jason
źródło

Odpowiedzi:

93

Kiedy klasa jest otwierana po raz pierwszy.

Statyczne konstruktory (przewodnik programowania w języku C #)

Konstruktor statyczny służy do inicjowania dowolnych danych statycznych lub wykonywania określonej akcji, która wymaga wykonania tylko raz. Jest wywoływana automatycznie przed utworzeniem pierwszej instancji lub utworzeniem odwołania do jakichkolwiek statycznych elementów członkowskich.

Carra
źródło
6
Ciekawe, że jest napisane „przed utworzeniem pierwszej instancji lub odwołaniem się do jakichkolwiek statycznych elementów członkowskich”. Istnieje pewna swoboda, kiedy faktycznie zostanie wywołana.
Tim Barrass
6
@TimBarrass z powodu innych wymagań specyfikacji okazuje się, że „przed” jest w rzeczywistości „bezpośrednio przed” - zobacz artykuł Jona Skeeta, do którego odwołuje się inna odpowiedź - stackoverflow.com/a/1437372/477420
Alexei Levenkov
A static constructor is used to initialize any static dataNIE. Lepiej używać static initializerdo inicjalizacji statycznych rzeczy.
Yousha Aleayoub
41

Nie jest to tak proste, jak można by się spodziewać, pomimo prostej dokumentacji. Artykuł Jona Skeeta http://csharpindepth.com/Articles/General/Beforefieldinit.aspx szczegółowo omawia tę kwestię.

Podsumowanie:

Konstruktor statyczny ma gwarancję wykonania bezpośrednio przed pierwszym odwołaniem do elementu członkowskiego tej klasy - albo utworzeniem instancji, albo własną statyczną metodą / właściwością klasy.

Zauważ, że statyczne inicjatory (jeśli nie ma statycznego konstruktora) gwarantują wykonanie w dowolnym momencie przed pierwszym odwołaniem się do określonego pola.

Greg Beech
źródło
Wspomniany artykuł jest teraz na stronie Jona Skeeta: csharpindepth.com/Articles/General/Beforefieldinit.aspx
Sudhanshu Mishra
Poniższe pytanie stackoverflow.com/questions/32525628/ ... pokaże przypadek, gdy „natychmiastowe” zachowanie jest dość oczywiste.
Alexei Levenkov
1
Właściwie miałem właśnie przypadek, w którym konstruktor statyczny został wywołany tuż przed rozpoczęciem wykonywania metody Main aplikacji konsolowej!
HerpDerpington
19

Konstruktor statyczny jest wywoływany przed użyciem czegokolwiek w klasie, ale dokładnie, kiedy to się stanie, zależy od implementacji.

Gwarantuje się, że zostanie wywołana przed uzyskaniem dostępu do pierwszego statycznego elementu członkowskiego i przed utworzeniem pierwszego wystąpienia. Jeśli klasa nigdy nie jest używana, nie ma gwarancji, że konstruktor statyczny zostanie w ogóle wywołany.

Guffa
źródło
2
Kiedy tak się dzieje, nie jest to „zależne od implementacji”, jeśli ta implementacja jest zgodna ze specyfikacją ECMA C #: „Wykonanie konstruktora statycznego jest wyzwalane przez pierwsze z następujących zdarzeń występujących w domenie aplikacji: [1] Wystąpienie klasa jest tworzona. [2] Istnieją odwołania do dowolnego statycznego elementu członkowskiego klasy. " (Sekcja 17.11, ecma-international.org/publications/standards/Ecma-334.htm )
LukeH,
1
@Luke: „Dokładny czas wykonania konstruktora statycznego zależy od implementacji” ondotnet.com/pub/a/dotnet/2003/07/07/staticxtor.html
Guffa
2
@Guffa: To może być interpretacja autora artykułu, ale nie znajdziesz tego sformułowania w specyfikacji C # w wersjach Microsoft lub ECMA / ISO.
LukeH
1

W przypadku wywołania metody statycznej z klasy nadrzędnej, konstruktor statyczny nie zostanie wywołany, chociaż jest on jawnie określony. Oto przykład, gdy konstruktor b nie jest wywoływany, jeśli zostanie wywołana metoda 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
    }
}    
Andrzej
źródło
1

Wygląda na to, że istnieje problem z konstruktorami statycznymi, na który udzielono odpowiedzi w innym miejscu, ale zajęło trochę czasu, aby przetrawić proste wyjaśnienie. Wszystkie dokumenty i objaśnienia twierdzą, że statyczny konstruktor / inicjatory są „gwarantowane” do uruchomienia przed utworzeniem instancji pierwszej klasy lub odwołaniem się do pierwszego pola statycznego. Gotcha pojawia się, gdy próbujesz umieścić statyczny singleton w klasie, która tworzy własną instancję (kura / jajko). W tym przypadku konstruktor statyczny jest wywoływany po konstruktorze instancji - aw moim przypadku konstruktor instancji zawierał kod, który opierał się na niektórych statycznych danych.

Konstruktor statyczny wywoływany po konstruktorze instancji?

Konstruktor statyczny może działać po konstruktorze niestatycznym. Czy to błąd kompilatora?

(odpowiedzią dla mnie było umieszczenie singletona w osobnej klasie lub ręczne zainicjowanie danych statycznych w konstruktorze instancji, zanim będzie to wymagane)

Etherman
źródło