2009-04-15 8 views

Antwort

14

Felder werden automatisch auf die logische Null für den Typ initialisiert; das ist implizit. Variablen müssen "eindeutige Zuordnung" erfüllen, daher muss zugewiesen werden, bevor sie gelesen werden können.

ECMA 334v4

§17.4.4 Feldinitialisierung

Der Anfangswert eines Feldes, ob es ein statisches Feld oder eine Instanz Feld sein, ist der Standardwert (Kapitel 12.2) von der Feldtyp. Es ist nicht möglich den Wert eines Feldes vor zu beobachten, diese Standardinitialisierung hat stattgefunden, und ein Feld ist somit nie "nicht initialisiert".

und

§12. Variablen

... Eine Variable muss definitiv zugewiesen werden (§12.3), bevor ihr Wert erhalten werden kann. ...

+0

Das ist nur noch die Frage zu wiederholen. Aber warum? –

+0

@YairHalberstadt das hängt davon ab, ob durch "warum?" man meint die Regel oder den Grund der Regel. Ich antwortete auf die erste, die wohl die Frage beantwortet; zum zweiten: weil man zu der Zeit, als man die Verkettung von Konstruktoren in Betracht gezogen hat, virtuelle Methoden während der Konstruktion aufgerufen hat und die Tatsache, dass auf der IL-Ebene Basiskonstruktoren an jeder Stelle der Aufrufkette aufgerufen werden können, fast unmöglich ist, etwas zu sagen sinnvoll bei Feldinitialisierung; Gleichermaßen können Felder überlappt werden, was es noch wichtiger macht, den Raum auf Null zu setzen, also ist kein Init technisch erforderlich - Kontrast ... –

+0

@YairHalberstadt lokale Variablen, die eine sehr einfache Zuweisungsprüfung haben, wo uninitialisiert normalerweise einen Fehler bedeutet und wo wir kann die Nullstellung überspringen (obwohl die aktuelle Laufzeit dies nie tut, IIRC). –

4

Eigentlich sollte es nicht. Ihr Fehler sollte in der zweiten Zeile, nicht der erste sein, und sollte sein, weil Sie es verwendet haben, bevor Sie es initialisierten.

Der Compiler hilft Ihnen hier.

Also initialisieren Sie sie nicht als Angewohnheit, sondern lassen Sie sich vom Compiler helfen!

Das schöne daran ist, dass es Pfad für Sie überprüfen wird. Wenn Sie eine switch-Anweisung mit 3 Fällen haben, in denen jeder den Wert festlegt, aber Sie vergessen, ihn in Ihrem "default" zu setzen, aber danach verwenden, werden Sie gewarnt, dass Sie einen Pfad verpasst haben.

Wenn Sie Variablen auf = 0 initialisieren, nehmen Sie diesen Vorteil weg.

+0

Ich habe auch Test1 verwendet, bevor ich es initialisierte, aber das war in Ordnung –

+0

Ja, die gleiche Überprüfung ist nicht hilfreich mit Klassenvariablen - es gibt keine Möglichkeit, diese zu verfolgen, es sei denn, Sie machen sie endgültig, dann sollte es sicherstellen, dass sie sind im Konstruktor ausgefüllt (eine gute Idee, wo möglich) –

+0

Obwohl seine Pfadprüfung nicht zu ausgefallen ist. ZB: Lass uns sagen, du hast so etwas: 'bool a, b = true; wenn (b) a = wahr; bool c = a; '. Die dritte Aussage ** wird den Fehler erzeugen, obwohl wir Menschen deutlich sehen, dass bis dahin "a" ** initialisiert wird. Der Compiler sieht nicht in die Bedingungen hinein - selbst wenn sie so einfach und immer wahr sind. (Und so gilt es auch für kompliziertere Fälle.) – Sushi271

2

Wie Marc angibt, das ist, was die Spezifikation sagt. Der Grund dafür ist, dass es ein paar gute Gründe gibt, ein Mitglied nicht initialisiert zu lassen, sondern eine lokale Variable, deren Lebensdauer durch die Methode begrenzt wird Variable ist zu initialisieren teuer und sollte nur unter bestimmten Verwendungsszenarien initialisiert werden. Ich für meinen Teil würde nicht initialisierte Mitglieder vermeiden, bis mein Rücken wirklich gegen die Wand war! Für lokale Variablen ist es auch viel einfacher zu erkennen, ob alle Codepfade wahrscheinlich zur Initialisierung führen, während es keine gute Heuristik gibt, um zu bestimmen, ob alle Codepfade über das gesamte Programm die Initialisierung vor der Verwendung garantieren. Eine völlig korrekte Antwort ist impossible in both cases, wie alle CS-Studenten wissen sollten.

12

Erweitern Marks Antwort, lokale Initialisierung der Variablen bezieht sich auch auf den Verifizierungsprozess.
Die CLI erfordert, dass in jedem überprüfbaren Code (dh Module, die nicht ausdrücklich den Überprüfungsvorgang mit der SkipVerfication-Eigenschaft aus dem Attribut SecurityPermission übersprungen haben) alle lokalen Variablen vor der Verwendung initialisiert werden müssen. Andernfalls wird VerficationException ausgelöst.

Interessanter ist, dass der Compiler das .locals init Flag automatisch auf jede Methode hinzufügt, die lokale Variablen verwendet. Dieses Flag bewirkt, dass der JIT-Compiler Code generiert, der alle lokalen Variablen auf ihre Standardwerte initialisiert. Das heißt, obwohl Sie sie bereits in Ihrem eigenen Code initialisiert haben, wird das JIT dem Flag .locals init entsprechen und den richtigen Initialisierungscode generieren. Diese "doppelte Initialisierung" wirkt sich nicht auf die Leistung aus, da der JIT-Compiler in Konfigurationen, die Optimierungen ermöglichen, die Duplizierung erkennt und sie effektiv als "toten Code" behandelt (die automatisch generierte Initialisierungsroutine erscheint nicht in den generierten Assembler-Anweisungen).

Laut Microsoft (auch von Eric Lippert als Antwort auf eine Frage auf seinem Blog unterstützt), in den meisten Fällen, wenn Programmierer ihre lokale Variable nicht initialisieren, tun sie es nicht, weil sie auf der zugrundeliegende Umgebung, um ihre Variable auf ihre Standardwerte zu initialisieren, aber nur, weil sie "vergessen" haben und somit manchmal illusorische logische Fehler verursachen.
Um also die Wahrscheinlichkeit zu reduzieren, dass Fehler dieser Art im C# -Code auftreten, besteht der Compiler darauf, dass Sie Ihre lokalen Variablen initialisieren. Obwohl das Flag .locals init dem generierten IL-Code hinzugefügt wird.

Eine ausführlichere Erklärung zu diesem Thema finden Sie hier: Behind The .locals init Flag

Verwandte Themen