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?
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:
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.
Wenn Sie sich Sorgen um die Reihenfolge machen, können Sie Ihren Code immer im statischen Konstruktor ablegen. Hier registriere ich meine Abhängigkeitseigenschaften.
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:
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.
Wenn Sie sich Sorgen um die Reihenfolge machen, können Sie Ihren Code immer im statischen Konstruktor ablegen. Hier registriere ich meine Abhängigkeitseigenschaften.
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?