Wie lautet die Initialisierungsreihenfolge der statischen Variablen in C #?

8

DependencyProperty.AddOwner MSDN-Seite bietet ein Beispiel mit zwei Klassen mit statischen Elementen. und das Mitglied einer Klasse hängt von dem Mitglied der anderen Klasse für die Initialisierung ab. Ich denke, dass MSDN falsch ist - die Reihenfolge der Initialisierung von statischen Variablen ist in C # unzuverlässig, so wie es ist in C ++ oder anderswo. Ich bin wahrscheinlich falsch, weil die WPF-Bibliothek selbst so geschrieben ist und es funktioniert gut. Was vermisse ich? Wie kann der C # -Compiler möglicherweise die sichere Initialisierungsreihenfolge kennen?

    
CannibalSmith 10.09.2009, 14:43
quelle

3 Antworten

23

Es ist in Ordnung, wenn ein Typ von einem anderen Typ abhängt, der initialisiert wird, solange Sie nicht in einem Zyklus enden.

Grundsätzlich ist das in Ordnung:

%Vor%

Das Ergebnis ist klar definiert. Die Initialisierer für statische Variablen von Child werden vor dem ersten Zugriff auf ein beliebiges statisches Feld in der Klasse gemäß Abschnitt 10.5.5.1 der Spezifikation ausgeführt.

Dies ist jedoch nicht:

%Vor%

In letzterem Fall haben Sie entweder mit Child.Nasty=0 , Parent.Y=10 , Child.X=10 oder Child.Nasty=0 , Parent.Y=0 , Child.X=10 abhängig davon, auf welche Klasse zuerst zugegriffen wird.

Der Zugriff auf Parent.Y first startet zuerst die Initialisierung von Parent . Die Initialisierung von Child wird erkennen, dass Parent initialisiert werden muss, aber die CLR weiß, dass sie bereits initialisiert wird, also unabhängig davon weiterläuft und zu der ersten Menge von Zahlen führt - weil Child.X vor der Initialisierung initialisiert wird Wert wird für Parent.Y verwendet.

Der Zugriff auf Child.Nasty beginnt mit der Initialisierung von Child zuerst, die dann mit der Initialisierung von Parent beginnt. Die Initialisierung von Parent wird erkennen, dass Child initialisiert werden muss, aber die CLR weiß, dass sie bereits initialisiert wird, also unabhängig davon fortfährt und zu der zweiten Menge von Zahlen führt.

Tun Sie das nicht.

EDIT: Okay, detailliertere Erklärung, wie versprochen.

Wann wird ein Typ initialisiert?

Wenn ein Typ einen statischen Konstruktor hat, wird er nur initialisiert Wenn es zum ersten Mal verwendet wird (entweder wenn ein statisches Element referenziert wird oder wenn eine Instanz erstellt wird). Wenn es nicht hat eine statische Konstruktor, es kann initial earler initialisiert werden. In der Theorie könnte es auch später initialisiert werden; Sie könnten theoretisch einen Konstruktor aufrufen oder eine statische Methode ohne die statischen Variablen zu initialisieren - aber muss initialisiert werden, bevor auf statische Variablen verwiesen wird.

Was passiert während der Initialisierung?

Zuerst erhalten alle statischen Variablen ihre Standardwerte (0, null) usw.).

Dann werden die statischen Variablen des Typs in Text initialisiert Auftrag. Wenn der Initialisierungsausdruck für eine statische Variable erforderlich ist ein anderer Typ wird initialisiert, dann wird dieser andere Typ sein vollständig initialisiert, bevor der Wert der Variablen zugewiesen wird - es sei denn, dieser zweite Typ wird bereits initialisiert (wegen a zyklische Abhängigkeit). Im Wesentlichen ist ein Typ entweder:

  • Bereits initialisiert
  • Im Moment initialisiert
  • Nicht initialisiert

Initialisierung wird nur ausgelöst, wenn der Typ nicht initialisiert ist. Dies bedeutet, dass es bei zyklischen Abhängigkeiten möglich ist Beobachten Sie den Wert einer statischen Variablen vor dem Anfangswert wurde zugewiesen . Das zeigt mein Child / Parent Beispiel.

Nachdem alle Initiatoren der statischen Variablen ausgeführt wurden, wird die statische Variable angezeigt Konstruktor wird ausgeführt.

Weitere Informationen zu diesem Thema finden Sie in Abschnitt 10.12 der C # Spezifikation.

Nach allgemeiner Nachfrage war hier meine ursprüngliche Antwort, als ich dachte, die Frage beträfe die Initialisierungsreihenfolge von statischen Variablen innerhalb einer Klasse :

Statische Variablen werden wie in Abschnitt 10.5.5.1 der C # -Spezifikation in textlicher Reihenfolge initialisiert:

  

Die Initialisierer für statische Feldvariablen   einer Klasse entsprechen einer Folge von   Zuweisungen, die in der. ausgeführt werden   textuelle Reihenfolge, in der sie erscheinen   die Klassendeklaration.

Beachten Sie, dass partielle Typen dies komplizierter machen, da es keine kanonische "textuelle Ordnung" der Klasse gibt.

    
Jon Skeet 10.09.2009, 14:47
quelle
0

Wenn Sie sich Sorgen um die Reihenfolge machen, können Sie Ihren Code immer im statischen Konstruktor ablegen. Hier registriere ich meine Abhängigkeitseigenschaften.

    
Taylor Leese 10.09.2009 14:49
quelle
0
___ qstnhdr ___ Wie lautet die Initialisierungsreihenfolge der statischen Variablen in C #? ___ tag123c ___ C # (sprich "Cis") ist eine objektorientierte Programmiersprache auf hohem Niveau, die für die Erstellung einer Vielzahl von Anwendungen entwickelt wurde, die auf dem .NET Framework (oder .NET Core) ausgeführt werden. C # ist einfach, leistungsfähig, typsicher und objektorientiert. ___ tag123wpf ___ Windows Presentation Foundation oder WPF ist ein Subsystem zum Rendern von Benutzeroberflächen in Windows-basierten Anwendungen. ___ answer1405729 ___

Es ist in Ordnung, wenn ein Typ von einem anderen Typ abhängt, der initialisiert wird, solange Sie nicht in einem Zyklus enden.

Grundsätzlich ist das in Ordnung:

%Vor%

Das Ergebnis ist klar definiert. Die Initialisierer für statische Variablen von %code% werden vor dem ersten Zugriff auf ein beliebiges statisches Feld in der Klasse gemäß Abschnitt 10.5.5.1 der Spezifikation ausgeführt.

Dies ist jedoch nicht:

%Vor%

In letzterem Fall haben Sie entweder mit %code% , %code% , %code% oder %code% , %code% , %code% abhängig davon, auf welche Klasse zuerst zugegriffen wird.

Der Zugriff auf %code% startet zuerst die Initialisierung von %code% . Die Initialisierung von %code% wird erkennen, dass %code% initialisiert werden muss, aber die CLR weiß, dass sie bereits initialisiert wird, also unabhängig davon weiterläuft und zu der ersten Menge von Zahlen führt - weil %code% vor der Initialisierung initialisiert wird Wert wird für %code% verwendet.

Der Zugriff auf %code% beginnt mit der Initialisierung von %code% zuerst, die dann mit der Initialisierung von %code% beginnt. Die Initialisierung von %code% wird erkennen, dass %code% initialisiert werden muss, aber die CLR weiß, dass sie bereits initialisiert wird, also unabhängig davon fortfährt und zu der zweiten Menge von Zahlen führt.

Tun Sie das nicht.

EDIT: Okay, detailliertere Erklärung, wie versprochen.

Wann wird ein Typ initialisiert?

Wenn ein Typ einen statischen Konstruktor hat, wird er nur initialisiert Wenn es zum ersten Mal verwendet wird (entweder wenn ein statisches Element referenziert wird oder wenn eine Instanz erstellt wird). Wenn es nicht hat eine statische Konstruktor, es kann initial earler initialisiert werden. In der Theorie könnte es auch später initialisiert werden; Sie könnten theoretisch einen Konstruktor aufrufen oder eine statische Methode ohne die statischen Variablen zu initialisieren - aber muss initialisiert werden, bevor auf statische Variablen verwiesen wird.

Was passiert während der Initialisierung?

Zuerst erhalten alle statischen Variablen ihre Standardwerte (0, null) usw.).

Dann werden die statischen Variablen des Typs in Text initialisiert Auftrag. Wenn der Initialisierungsausdruck für eine statische Variable erforderlich ist ein anderer Typ wird initialisiert, dann wird dieser andere Typ sein vollständig initialisiert, bevor der Wert der Variablen zugewiesen wird - es sei denn, dieser zweite Typ wird bereits initialisiert (wegen a zyklische Abhängigkeit). Im Wesentlichen ist ein Typ entweder:

  • Bereits initialisiert
  • Im Moment initialisiert
  • Nicht initialisiert

Initialisierung wird nur ausgelöst, wenn der Typ nicht initialisiert ist. Dies bedeutet, dass es bei zyklischen Abhängigkeiten möglich ist Beobachten Sie den Wert einer statischen Variablen vor dem Anfangswert wurde zugewiesen . Das zeigt mein %code% / %code% Beispiel.

Nachdem alle Initiatoren der statischen Variablen ausgeführt wurden, wird die statische Variable angezeigt Konstruktor wird ausgeführt.

Weitere Informationen zu diesem Thema finden Sie in Abschnitt 10.12 der C # Spezifikation.

Nach allgemeiner Nachfrage war hier meine ursprüngliche Antwort, als ich dachte, die Frage beträfe die Initialisierungsreihenfolge von statischen Variablen innerhalb einer Klasse :

Statische Variablen werden wie in Abschnitt 10.5.5.1 der C # -Spezifikation in textlicher Reihenfolge initialisiert:

  

Die Initialisierer für statische Feldvariablen   einer Klasse entsprechen einer Folge von   Zuweisungen, die in der. ausgeführt werden   textuelle Reihenfolge, in der sie erscheinen   die Klassendeklaration.

Beachten Sie, dass partielle Typen dies komplizierter machen, da es keine kanonische "textuelle Ordnung" der Klasse gibt.

    
___ answer1405740 ___

Wenn Sie sich Sorgen um die Reihenfolge machen, können Sie Ihren Code immer im statischen Konstruktor ablegen. Hier registriere ich meine Abhängigkeitseigenschaften.

    
___ qstntxt ___

DependencyProperty.AddOwner MSDN-Seite bietet ein Beispiel mit zwei Klassen mit statischen Elementen. und das Mitglied einer Klasse hängt von dem Mitglied der anderen Klasse für die Initialisierung ab. Ich denke, dass MSDN falsch ist - die Reihenfolge der Initialisierung von statischen Variablen ist in C # unzuverlässig, so wie es ist in C ++ oder anderswo. Ich bin wahrscheinlich falsch, weil die WPF-Bibliothek selbst so geschrieben ist und es funktioniert gut. Was vermisse ich? Wie kann der C # -Compiler möglicherweise die sichere Initialisierungsreihenfolge kennen?

    
___
Akash Kava 10.09.2009 14:57
quelle

Tags und Links