wake-up-neo.com

Warum müssen lokale Variablen initialisiert werden, Felder jedoch nicht?

Wenn ich in meiner Klasse einen Bool erstelle, ist das ungefähr bool check ist der Standardwert false.

Wenn ich den gleichen Bool in meiner Methode erstelle, wird bool check (anstelle von innerhalb der Klasse), bekomme ich eine Fehlermeldung "Verwendung von nicht zugeordneten lokalen Variablen prüfen". Warum?

139
nachime

Wenn ich in meiner Methode bool check (anstelle der Klasse) denselben Bool erstelle, wird die Fehlermeldung "Verwendung der nicht zugewiesenen lokalen Variablen check" angezeigt. Warum?

Weil der Compiler versucht, Sie daran zu hindern, einen Fehler zu machen.

Ändert die Initialisierung Ihrer Variablen in false etwas an diesem bestimmten Ausführungspfad? Wahrscheinlich nicht, wenn man bedenkt, dass default(bool) ohnehin falsch ist, aber es zwingt Sie, sich dessen bewusst zu sein dass dies geschieht. Die .NET-Umgebung verhindert, dass Sie auf "Garbage Memory" zugreifen, da hierdurch alle Werte auf ihre Standardwerte zurückgesetzt werden. Stellen Sie sich dennoch vor, dies wäre ein Referenztyp, und Sie würden einen nicht initialisierten (Null-) Wert an eine Methode übergeben, die einen Nicht-Null-Wert erwartet, und zur Laufzeit eine NRE abrufen. Der Compiler versucht lediglich, dies zu verhindern und akzeptiert, dass dies manchmal zu bool b = false Aussagen.

Eric Lippert spricht darüber in einem Blogbeitrag :

Der Grund, warum wir dies illegal machen wollen, ist, wie viele Leute glauben, nicht, dass die lokale Variable zu Müll initialisiert wird und wir möchten Sie vor Müll schützen. Tatsächlich initialisieren wir Einheimische automatisch auf ihre Standardwerte. (In den Programmiersprachen C und C++ ist dies nicht der Fall, und Sie können fröhlich Müll von einem nicht initialisierten lokalen Computer lesen.) Stattdessen liegt es daran, dass das Vorhandensein eines solchen Codepfads wahrscheinlich ein Fehler ist , und wir möchten Sie in die Grube der Qualität werfen; Sie sollten hart arbeiten müssen, um diesen Fehler zu schreiben.

Warum gilt das nicht für ein Klassenfeld? Nun, ich gehe davon aus, dass die Linie irgendwo gezogen werden musste und die Initialisierung lokaler Variablen im Gegensatz zu Klassenfeldern viel einfacher zu diagnostizieren und zu korrigieren ist. Der Compiler könnte dies tun, aber denken Sie an alle möglichen Überprüfungen, die durchgeführt werden müssten (wobei einige von dem Klassencode selbst unabhängig sind), um zu bewerten, ob jedes Feld in einem Klasse wird initialisiert. Ich bin kein Compiler Designer, aber ich bin mir sicher, dass es definitiv härter ist, da es viele Fälle gibt, die berücksichtigt werden und die auf eine rechtzeitige Weise erledigt werden müssen auch. Für jede Funktion, die Sie entwerfen, schreiben, testen und bereitstellen müssen, ist der Wert der Implementierung im Gegensatz zum Aufwand unrentabel und kompliziert.

27
Yuval Itzchakov

Warum müssen lokale Variablen initialisiert werden, Felder jedoch nicht?

Die kurze Antwort lautet, dass Code, der auf nicht initialisierte lokale Variablen zugreift, vom Compiler mithilfe einer statischen Analyse zuverlässig erkannt werden kann. Dies ist jedoch nicht bei Feldern der Fall. Der Compiler erzwingt also den ersten Fall, aber nicht den zweiten.

Warum müssen lokale Variablen initialisiert werden?

Dies ist nicht mehr als eine Entwurfsentscheidung der C # -Sprache, wie erklärt von Eric Lippert . Die CLR und die .NET-Umgebung erfordern dies nicht. VB.NET kann beispielsweise problemlos mit nicht initialisierten lokalen Variablen kompiliert werden, und in Wirklichkeit initialisiert die CLR alle nicht initialisierten Variablen auf Standardwerte.

Das Gleiche könnte mit C # passieren, aber die Sprachentwickler entschieden sich dagegen. Der Grund dafür ist, dass initialisierte Variablen eine große Fehlerquelle darstellen und der Compiler durch das Anfordern der Initialisierung dazu beiträgt, versehentliche Fehler zu vermeiden.

Warum müssen Felder nicht initialisiert werden?

Warum findet diese obligatorische explizite Initialisierung nicht für Felder innerhalb einer Klasse statt? Ganz einfach, weil diese explizite Initialisierung während der Erstellung auftreten kann, indem eine Eigenschaft von einem Objektinitialisierer oder sogar von einer Methode aufgerufen wird, die lange nach dem Ereignis aufgerufen wird. Der Compiler kann nicht mithilfe der statischen Analyse feststellen, ob jeder mögliche Pfad durch den Code dazu führt, dass die Variable explizit vor uns initialisiert wird. Es wäre ärgerlich, es falsch zu verstehen, da dem Entwickler gültiger Code verbleiben könnte, der nicht kompiliert werden kann. C # erzwingt dies also überhaupt nicht, und die CLR initialisiert die Felder automatisch auf einen Standardwert, wenn dieser nicht explizit festgelegt wird.

Was ist mit Sammlungsarten?

Die Durchsetzung der lokalen Variableninitialisierung durch C # ist begrenzt, was Entwickler häufig herausfordert. Betrachten Sie die folgenden vier Codezeilen:

string str;
var len1 = str.Length;
var array = new string[10];
var len2 = array[0].Length;

Die zweite Codezeile wird nicht kompiliert, da versucht wird, eine nicht initialisierte Zeichenfolgenvariable zu lesen. Die vierte Codezeile wird zwar problemlos kompiliert, da array initialisiert wurde, jedoch nur mit Standardwerten. Da der Standardwert einer Zeichenfolge null ist, wird zur Laufzeit eine Ausnahme ausgegeben. Jeder, der Zeit mit Stack Overflow verbracht hat, wird wissen, dass diese explizite/implizite Initialisierungsinkonsistenz zu einer großen Anzahl von Fehlern führt. Fragen.

25
David Arno

Gute Antworten oben, aber ich dachte, ich würde eine viel einfachere/kürzere Antwort für Leute posten, die faul sind, eine lange zu lesen (wie ich selbst).

Klasse

class Foo {
    private string Boo;
    public Foo() { /** bla bla bla **/ }
    public string DoSomething() { return Boo; }
}

Die Eigenschaft Boo kann oder kann not im Konstruktor initialisiert worden sein. Also, wenn es findet return Boo; es ist nicht vorausgesetzt dass es initialisiert wurde. Es wird einfach unterdrückt der Fehler.

Funktion

public string Foo() {
   string Boo;
   return Boo; // triggers error
}

Das { } Zeichen definieren den Umfang eines Codeblocks. Der Compiler geht die Zweige dieser { } Blöcke, die den Überblick behalten. Es kann leicht sagen, dass Boo nicht initialisiert wurde. Der Fehler wird dann ausgelöst.

Warum existiert der Fehler?

Der Fehler wurde eingeführt, um die Anzahl der Codezeilen zu verringern, die erforderlich sind, um den Quellcode sicher zu machen. Ohne den Fehler würde das oben genannte so aussehen.

public string Foo() {
   string Boo;
   /* bla bla bla */
   if(Boo == null) {
      return "";
   }
   return Boo;
}

Aus dem Handbuch:

Der C # -Compiler erlaubt die Verwendung nicht initialisierter Variablen nicht. Wenn der Compiler die Verwendung einer Variablen erkennt, die möglicherweise nicht initialisiert wurde, generiert er den Compilerfehler CS0165. Weitere Informationen finden Sie unter Felder (C # -Programmierhandbuch). Beachten Sie, dass dieser Fehler generiert wird, wenn der Compiler auf ein Konstrukt stößt, das möglicherweise zur Verwendung einer nicht zugewiesenen Variablen führt, auch wenn Ihr bestimmter Code dies nicht tut. Dies vermeidet die Notwendigkeit übermäßig komplexer Regeln für die eindeutige Zuordnung.

Referenz: https://msdn.Microsoft.com/en-us/library/4y7h161d.aspx

10
Reactgular