Wie funktioniert statisches Feld-Initialisierung funktioniert in C#?
Sollten statische Feld-Initialisierung abgeschlossen sein, bevor der Konstruktor aufgerufen wird?
Das folgende Programm liefert eine Ausgabe, die scheint nicht korrekt zu mir.
new A()
_A == null
static A()
new A()
_A == A
Code:
public class A
{
public static string _A = (new A()).I();
public A()
{
Console.WriteLine("new A()");
if (_A == null)
Console.WriteLine("_A == null");
else
Console.WriteLine("_A == " + _A);
}
static A()
{
Console.WriteLine("static A()");
}
public string I()
{
return "A";
}
}
class Program
{
static void Main(string[] args)
{
var a = new A();
}
}
- FWIW, ich werde erwähnen, dass, wenn man will, zu verzögern einige "statische" Initialisierung bis zu einem bestimmten statisches Feld aufgerufen wird, eine Möglichkeit, dies zu tun (für ein Feld, das ein Referenz-Typ) ist ein privates statisches Feld, die beginnt, die out-null, und dann eine öffentliche, statische getter oder Methode, die die "Initialisierung" nur wenn der Wert null ist, dann setzt privaten Bereich und gibt es zurück.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist korrekt.
Ihre statischen Initialisierungen, dann wird der statische Konstruktor ausgeführt wird, bevor Sie Ihre standard-Konstruktor, aber wenn es läuft, ist es mit new A(), also, die durch Ihre nicht-statische Konstruktor Weg. Dies bewirkt, dass die Nachrichten, die Sie sehen.
Hier ist der vollständige Pfad der Ausführung:
Beim ersten Aufruf
var a = new A();
in Ihrem Programm, dies ist das erste mal Eine zugegriffen wird.Dadurch wird das Feuer aus der statischen Initialisierung von
A._A
An dieser Stelle, A. _A Konstrukte mit
_A = (new A()).I();
Dies trifft
da an dieser Stelle, _A wurde noch nicht festgelegt haben, ist den zurückgegebenen, konstruierten Typs (noch) nicht.
Nächsten, der statische Konstruktor
A { static A(); }
ausgeführt wird. Dies druckt die "static A ()" - Meldung.Endlich, Ihre ursprüngliche Aussage (
var a = new A();
) ausgeführt wird, aber an diesem Punkt, der Statik aufgebaut werden, so erhalten Sie den endgültigen Druck.Einer extra-Seite beachten - die C# - Spezifikation (ich freue mich auf 4.0, aber es ist es in 3.0 auch), sagt in 10.5.5.1 Statische Feld-Initialisierung:
Haben Sie einen statischen Konstruktor, so dass die "Sonst" - Klausel nicht gilt. Aber ich denke, dass es relevante Informationen, um Ihre Frage zu wissen, dass, wenn Sie nicht über einen statischen Konstruktor, das statische Feld-Initialisierungen ausgeführt werden kann ', auf eine von der Implementierung abhängige Zeit'. Dies könnte die Angelegenheit, wenn Ihre statische Feld-Initialisierer ist zu tun, irgendeine Art von Daten-Initialisierung oder die Objekt-Erstellung, die Sie verlassen sich auf, ohne Zugriff auf das statische Feld selbst.
Es ist esoterisch, glaube ich, aber ich sah es heute passieren als 'von der Implementierung abhängige Zeit' scheint sich verändert zu haben zwischen C# 3.0-und 4.0 - zumindest für die situation, die ich war auf der Suche. Die einfache Lösung ist natürlich einfach - fügen Sie einfach einen statischen Konstruktor...
Ich tatsächlich glauben, dass Sie tut, was Sie denken. Ihr test ist es schwer zu sagen.
Ihre Initialisierung für _A
Erste erstellt eine neue Instanz Ein, so werden Ihre Schriften neu Ein() und _A = null. Da war es null, wenn es begann, als diese ist die Initialisierung. Nachdem zuerst entsprechend formatiert, wird der statische Konstruktor aufgerufen wird, liefert die neue Instanz.
Scheint es der compiler tut das erwartete.
1. - Alle statischen code ausgeführt wird (Felder zuerst, dann static-Konstruktor) in der Klasse:
2. - Klasse-Konstruktor aufgerufen wird:
Du fragst, warum dies möglich ist. Naja, meiner Meinung nach, eine Instanz nicht unbedingt erforderlich, dass alle Klassenvariablen initialisiert werden bei der Erstellung. Es erfordert nur Sie muss vorhanden sein. Ich denke, in diesem speziellen Fall unterstützt diesen Gedanken, da eine Instanz erstellt wird, bevor alle statischen Initialisierung gemacht wird.
Ja, statische Felder Initialisierung sollte abgeschlossen sein, bevor der Konstruktor aufgerufen wird. Aber Sie setzen compiler in der unnormalen situation und es kann einfach nicht gehorchen dieser Regel.
Dies ist interessanter trick, aber es ist nicht gonna passieren in der normalen Anwendung.