C# - variable scoping: 'x' deklariert werden können, in diesem Umfang, weil es geben würde, eine andere Bedeutung für 'x'
if(true)
{
string var = "VAR";
}
string var = "New VAR!";
Dieser Folge:
Fehler 1 Eine lokale variable mit dem Namen 'var'
deklariert werden können, in diesem Umfang
weil es eine andere
Bedeutung 'var', das ist schon
in einem 'Kind' Bereich zu bezeichnen
etwas anderes ist.
Nichts weltbewegendes eigentlich, aber ist das nicht einfach nur falsch? Fellow Entwickler und ich wurden gefragt, ob die erste Erklärung sollte in einem anderen Bereich, so ist die zweite Erklärung kann nicht eingreifen mit der ersten Erklärung.
Warum ist C# nicht in der Lage zu unterscheiden zwischen die beiden Bereiche? Sollte die erste IF-Bereich nicht völlig getrennt vom rest der Methode?
Kann ich nicht aufrufen var von außen, wenn also die Fehlermeldung ist falsch, denn die erste var hat keine Relevanz in dem zweiten Bereich.
Ähnlich wie stackoverflow.com/questions/296755/child-scope-cs0136
Ich nehme an, du bist mit C# 2.0, da
var
ist ein Schlüsselwort in C# 3.0.sieht aus wie Sie fallen in die Falle der Annahme, dass C# viel eher wie C++ aus als es wirklich ist. Versuchen Sie nicht, auf Grund von dem, was C++ nicht, was C# funktioniert -- das ist gefährliches Terrain!
var ist nicht reserved - Schlüsselwort von C# 3.0. "var" bedeutet lediglich "implizit geben diese lokale variable", wenn (1) es wird als die Art der Deklaration einer lokalen Variablen (oder mit der block-decl-oder foreach, oder, und so weiter) UND (2) wenn es nicht einen Typ mit dem Namen "var" bereits im Umfang. C# hat nie Hinzugefügt ein reserviertes Schlüsselwort, da C# 1; alle neuen Schlüsselwörter sind contextual keywords. Sie haben nur Bedeutung als Stichworte, wenn es in den Kontext, der Ihnen die Bedeutung zu; Sie sind juristische Bezeichner sonst.
InformationsquelleAutor | 2010-01-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das Problem hier ist größtenteils von guter Praxis und zur Vorbeugung gegen ungewollte Fehler. Zugegeben, der C# - compiler könnte theoretisch so gestaltet werden, dass kein Konflikt zwischen den Bereichen hier. Das würde doch viel Aufwand für wenig Gewinn, so wie ich es sehe.
Überlegen, dass, wenn die Erklärung der
var
im übergeordneten scope vor wird die if-Anweisung, es wäre ein unauflöslicher Konflikte. Der compiler einfach nicht unterscheiden zwischen den folgenden beiden Fällen. Die Analyse erfolgt rein auf Umfang, und nicht der Reihenfolge der Deklaration/Verwendung, wie Sie zu sein scheinen, erwartet.Theoretisch akzeptabel (aber immer noch ungültig, so weit wie C# geht):
und inakzeptabel (da wäre das verstecken des parent-variable):
werden behandelt, sondern auch genau die gleichen in Bezug auf Variablen und scopes.
Nun, gibt es eine eigentliche Grund in dieser secenario, warum Sie können nicht nur eine der Variablen einen anderen Namen? Ich gehe davon aus (hoffe) Ihren tatsächlichen Variablen werden nicht genannt
var
, so dass ich nicht wirklich sehen dies als ein problem. Wenn Sie noch auf der Absicht der Wiederverwendung der gleichen Variablen-Namen, nur setzen Sie Sie in Geschwister-Bereiche:Diese jedoch während der Gültigkeit der compiler kann dazu führen, eine gewisse Menge an Verwirrung beim Lesen des Codes, so dass ich empfehlen, gegen den es in fast jedem Fall.
Ja genau - es ist nicht erlaubt, einfach weil es zu Verwirrung führen kann/wird als schlechte design-Praxis.
gut gesehen, die aus IL-Sicht Im ziemlich sicher, dass die if - {} scope nicht vorhanden, so würde es bedeuten, dass der compiler tricks für den Wert von möglichen Verwechslungen, so wenn im richtigen es ist nicht aktiv verboten, aber passiv. Die benötigte Funktion ist einfach nicht implementiert
Durch die Art und Weise, Sie sagte in einem Kommentar zu einem gelöschten Beitrag, der eine bedingte Anweisung erstellt einen Rahmen. Es ist sicherlich nicht. Ein block erzeugt einen Rahmen. Zahlreiche äußerungen Bereiche erstellen -- for, foreach, using, try/catch/finally und so weiter. Jedoch die bedingte Anweisung ist nicht einer von Ihnen; der Umfang erstellt wird erstellt, indem der block, nicht durch die bedingte.
Vertrauen Sie, um zu zeigen, dass so etwas wie out. 🙂 Sie sind natürlich Recht, aber es ist ein eher subtiler Punkt. Es ist effektiv die geschweiften Klammern bedeuten, dass ein block, mit den bemerkenswerten Ausnahmen Sie wies darauf hin,, bedeuten, dass ein block. Korrigieren Sie mich, wenn ich falsch Liege, aber wenn Aussagen mit one-line-Maßnahmen nicht enthalten, die Kind-scope(s)?
InformationsquelleAutor Noldorin
Nein, das ist nicht falsch. Dies ist eine korrekte Implementierung der in Abschnitt 7.5.2.1 der C# - Spezifikation "Simple Namen, invariante Bedeutungen in den Blöcken".
Die Spezifikation besagt:
Die Frage ist unsinnig; offensichtlich ist der compiler ist in der Lage zu differenzieren zwischen den beiden Bereichen. Wenn der compiler nicht in der Lage waren, zu unterscheiden zwischen die beiden Bereiche dann wie könnte man den Fehler produziert werden? Die Fehlermeldung sagt, dass es zwei verschiedene Bereiche, und damit die Bereiche wurden differenziert!
Nein, sollte es nicht. Der Umfang (und lokale Variablen-deklarations-Raum) definiert, die durch die block-Anweisung in der Folge der bedingten Anweisung ist lexikalisch ein Teil der äußeren block definiert die Körper der Methode. Daher, Regeln über den Inhalt des äußeren block gelten für die Inhalte der inneren block.
Dies ist völlig falsch. Es ist irreführend zu folgern, dass nur weil die lokale variable nicht mehr in Reichweite, dass die äußeren block keinen Fehler enthält. Die Fehlermeldung ist korrekt.
Den Fehler hier hat nichts damit zu tun, ob der Geltungsbereich einer variable überschneidet sich der Geltungsbereich einer anderen variable; das einzige, was hier relevant ist ist, dass Sie einen block -- der äußeren block-in der gleichen einfachen Namen wird verwendet, um beziehen sich auf zwei völlig verschiedene Dinge. C# erfordert, dass Sie einen einfachen Namen haben eine Bedeutung im ganzen block, die zuerst verwendet es.
Beispiel:
Dass ist völlig legal; der Umfang der äußeren x überschneidet sich der Geltungsbereich des inneren x, aber das ist nicht ein Fehler. Was ist ein Fehler:
da jetzt den einfachen Namen "x" bedeutet, dass zwei verschiedene Dinge, die im inneren des Körpers der M-es bedeutet".x" und die lokale variable "x". Es ist verwirrend für Entwickler und code-Betreuer, wenn die gleichen einfachen Namen bedeutet zwei völlig verschiedene Dinge in dem gleichen block, so dass illegal ist.
Wir erlauben parallele Blöcke enthalten die gleichen einfachen Namen auf zwei verschiedene Arten verwendet; das ist legal:
weil jetzt der einzige block, der enthält zwei inkonsistente Verwendungen von x ist der äußere block, und , dass der block nicht direkt enthalten keine Verwendung von "x", nur indirekt.
Guter Punkt; obwohl in der Tat die Frage, ob wir reden hier über den block, wie die Deklaration einer lokalen Variablen Raum, oder den block als Gültigkeitsbereich einer lokalen Variablen, ist so ziemlich irrelevant für die Frage. Das problem scheinbar zu sein, über die Erklärung von Raum, seit der Erklärung gekennzeichnet ist. Aber in der Tat ist es über scope -- haben wir zwei Unternehmen, die beide blickte durch Ihre unqualifizierten Namen erfolgreich, gebunden und auf verschiedene Entitäten in der gleichen block.
Das Beispiel mit dem Feld und die lokale variable mit dem gleichen Namen, auf die zugegriffen wird, aus dem gleichen block ist wahrscheinlich die einzige Beleuchtung, die mit Bezug auf die Begründung dieser design-Entscheidung.
Vielleicht nur mich, aber der Allgemeine Ton Ihrer Antwort, scheint ein bisschen aggressiv.
Sie interessieren könnte, meinen Aufsatz zu Lesen zu diesem Thema: blogs.msdn.com/b/ericlippert/archive/2008/02/20/...
InformationsquelleAutor Eric Lippert
Dies gilt in C++, aber eine Quelle für viele Fehler und schlaflose Nächte. Ich denke, die C# - Leute haben sich dafür entschieden, dass es besser ist zu werfen eine Warnung/Fehler, da es in der überwiegenden Mehrzahl der Fälle, einen Fehler eher als etwas, was der Programmierer eigentlich will.
Hier's eine interessante Diskussion auf, welche Teile der Spezifikation dieser Fehler kommt.
BEARBEITEN (einige Beispiele) -----
In C++ ist, gilt Folgendes (und es spielt keine Rolle, wenn die äußere Erklärung ist, bevor oder nachdem der innere Umfang ist, wird es nur interessanter und bug-anfällig ist, wenn es vor).
Nun stellen Sie die Funktion ein paar Zeilen mehr, und es könnte leicht sein, um nicht vor Ort den Fehler. Der compiler beschwert sich nie (nicht den alten Tagen, nicht sicher über neuere Versionen von C++), und die Funktion gibt immer 0 zurück.
Den behaivour ist eindeutig ein Fehler, also wäre es gut, wenn ein c++-lint Programm oder der compiler darauf hinweisen. Wenn es nicht ein Fehler ist es leicht zu umgehen, indem Sie einfach die Umbenennung der innere variable.
Um Beleidigung Verletzung hinzuzufügen ich erinnere mich, dass GCC und VS6 hatten unterschiedliche Meinungen, wo die counter-variable in for-Schleifen gehörte. Man sagte, es gehörte zu dem äußeren Umfang, und der andere sagte es nicht. Ein bisschen ärgerlich um die Arbeit an cross-Plattform-code. Lassen Sie mich Ihnen noch ein Beispiel, um meine Zeile zu zählen.
Dieser code war in VS6 IIRC und nicht in GCC. Eh, C#, hat aufgeräumt, ein paar Dinge, die gut ist.
InformationsquelleAutor Mats Fredriksson