Wann wird ein statischer Konstruktor in C # aufgerufen?

86

Wenn ich eine Klasse habe, die einen statischen Konstruktor enthält, wird dieser Konstruktor aufgerufen, wenn die Assembly, die die Klasse enthält, zum ersten Mal geladen wird oder wenn der erste Verweis auf diese Klasse getroffen wird?

Jason
quelle

Antworten:

91

Wenn zum ersten Mal auf die Klasse zugegriffen wird.

Statische Konstruktoren (C # -Programmierhandbuch)

Ein statischer Konstruktor wird verwendet, um statische Daten zu initialisieren oder eine bestimmte Aktion auszuführen, die nur einmal ausgeführt werden muss. Es wird automatisch aufgerufen, bevor die erste Instanz erstellt oder auf statische Elemente verwiesen wird.

Carra
quelle
6
Interessant, dass dort steht, "bevor die erste Instanz erstellt wird oder auf statische Mitglieder verwiesen wird". Es gibt einen gewissen Spielraum, wenn es tatsächlich aufgerufen wird.
Tim Barrass
6
@ TimBarrass aufgrund einiger anderer Anforderungen der Spezifikation stellt sich heraus, dass "vor" tatsächlich "unmittelbar vor" ist - siehe Jon Skeets
Alexei Levenkov
A static constructor is used to initialize any static dataNEIN. Besser zum static initializerInitialisieren statischer Daten.
Yousha Aleayoub
41

Es ist nicht ganz so einfach, wie Sie es trotz einfacher Dokumentation erwarten würden. Jon Skeets Artikel http://csharpindepth.com/Articles/General/Beforefieldinit.aspx geht ausführlich auf diese Frage ein.

Zusammenfassung:

Der statische Konstruktor wird garantiert unmittelbar vor dem ersten Verweis auf ein Mitglied dieser Klasse ausgeführt - entweder die Erstellung einer Instanz oder eine eigene statische Methode / Eigenschaft der Klasse.

Beachten Sie, dass statische Initilizer (wenn kein statischer Konstruktor vorhanden ist) garantiert jederzeit ausgeführt werden können, bevor zuerst auf ein bestimmtes Feld verwiesen wird.

Greg Beech
quelle
Der erwähnte Artikel ist jetzt auf Jon Skeets
Sudhanshu Mishra
Die folgende Frage stackoverflow.com/questions/32525628/… zeigt den Fall, dass "sofortiges" Verhalten ganz offensichtlich ist.
Alexei Levenkov
1
Ich hatte gerade den Fall, dass ein statischer Konstruktor aufgerufen wurde, kurz bevor die Hauptmethode einer Konsolenanwendung überhaupt ausgeführt wurde!
HerpDerpington
19

Der statische Konstruktor wird aufgerufen, bevor Sie etwas in der Klasse verwenden. Wann genau dies geschieht, hängt jedoch von der Implementierung ab.

Es wird garantiert aufgerufen, bevor auf das erste statische Mitglied zugegriffen wird und bevor die erste Instanz erstellt wird. Wenn die Klasse nie verwendet wird, kann nicht garantiert werden, dass der statische Konstruktor überhaupt aufgerufen wird.

Guffa
quelle
2
Wenn dies geschieht, liegt es nicht an der Implementierung, wenn diese Implementierung der ECMA-C # -Spezifikation folgt: "Die Ausführung eines statischen Konstruktors wird durch das erste der folgenden Ereignisse ausgelöst, die innerhalb einer Anwendungsdomäne auftreten: [1] Eine Instanz der Klasse wird erstellt. [2] Auf alle statischen Mitglieder der Klasse wird verwiesen. " (Abschnitt 17.11 , ecma-international.org/publications/standards/Ecma-334.htm )
LukeH
@Luke: „Der genaue Zeitpunkt der statischen Konstruktor Ausführung ist implementierungsabhängig“ ondotnet.com/pub/a/dotnet/2003/07/07/staticxtor.html
Guffa
2
@Guffa: Das könnte die Interpretation des Artikelautors sein, aber Sie werden diesen Wortlaut nicht in den Microsoft- oder ECMA / ISO-Versionen der C # -Spezifikation finden.
LukeH
1

Wenn die statische Methode von der übergeordneten Klasse aufgerufen wird, wird der statische Konstruktor nicht aufgerufen, obwohl er explizit angegeben ist. Hier ist ein Beispiel. Der Konstruktor b wird nicht aufgerufen, wenn b.methoda () aufgerufen wird.

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

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

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

Es scheint eine Gotcha mit statischen Konstruktoren zu geben, die an anderer Stelle beantwortet wird, aber eine Weile gebraucht hat, um eine einfache Erklärung zu finden. In allen Dokumenten und Erklärungen wird behauptet, dass die Ausführung des statischen Konstruktors / der Initialisierer "garantiert" ist, bevor die erste Klasse instanziiert oder auf das erste statische Feld verwiesen wird. Das Gotcha kommt herein, wenn Sie versuchen, einen statischen Singleton in die Klasse einzufügen, der eine Instanz von sich selbst erstellt (Huhn / Ei). In diesem Fall wird der statische Konstruktor nach dem Instanzkonstruktor aufgerufen - und in meinem Fall enthielt der Instanzkonstruktor Code, der auf einigen statischen Daten beruhte.

Statischer Konstruktor nach Instanzkonstruktor aufgerufen?

Der statische Konstruktor kann nach dem nicht statischen Konstruktor ausgeführt werden. Ist das ein Compiler-Fehler?

(Die Antwort für mich war, den Singleton in eine separate Klasse zu stellen oder die statischen Daten im Instanzkonstruktor manuell zu initialisieren, bevor sie benötigt werden.)

Etherman
quelle