Donnerstag, Februar 27, 2020

Kind-Bereich & CS0136

Den folgenden code zu kompilieren, schlägt fehl, die besagt „Eine lokale variable mit dem Namen ’st‘ deklariert werden können, in diesem Umfang, da würde es eine andere Bedeutung geben ’st‘, die bereits in ein „Kind“ Bereich zu bezeichnen, dass etwas anderes“:

        var l = new List<string>();
        l.Find(st => st.EndsWith("12"));
        string st = "why this fails?";

Verstehe ich, warum dies nicht funktioniert:

        string preParent = "";
        {
            string preParent = "Should fail cause we change the meaning";
        }

Wenn wir die bekommen wir „CS0103: Der name ‚postParent‘ existiert nicht im aktuellen Kontext“:

        {
            string postParent=string.Empty;
        }
        postParent = "Should this work?";

Was ich nicht verstehe ist, warum ist der compiler schlau genug, um zu sehen, dass postParent ist nicht im Umfang, aber nicht lassen Sie mich eine neue variable definieren, die denselben Namen hat wie eine variable in einem untergeordneten Bereich (was offensichtlich aus dem Rahmen an dieser Stelle).

Ist der compiler, der einfachen Durchsetzung Umfang durch die Weigerung, lassen Sie mich mit der Variablen? Wenn ja, das macht Sinn.

===========

Bearbeitet:

Ich denke, was ich auch interessant finde, ist wie Sie können die gleiche variable innerhalb von zwei untergeordnete Bereiche in eine einzelne Methode, so gilt:

        {
            string thisWorks= string.Empty;
        }
        {
            string thisWorks= "Should this work?";
        }

Ich bin nur ein wenig neugierig, dass Sie können zwei Variablen mit dem gleichen Namen, solange Sie auf dem gleichen Niveau (wenn man sich als Umfang eines Baumes). Dies macht Sinn, denn Sie können lokale Variablen, die in beiden Methoden der gleichen Klasse mit dem gleichen Namen.

Ich bin nur überrascht, dass der compiler in der Lage ist zu differenzieren und dies erlauben, während Sie würde nicht zulassen, dass die postParent variable. Und dies ist eine technische Einschränkung, oder war dies eine design-Entscheidung? Das ist, was ich wirklich erreichen wollte;-)

  • Warum downvote nach 5 Monaten jetzt?
InformationsquelleAutor JoshBerke | 2008-11-17

2 Kommentare

  1. 12

    Ja, der compiler ist die Durchsetzung Umfang. Beachten Sie, dass der Gültigkeitsbereich einer Variablen ist der lexikalische block es ist ein Teil – nicht nur aus der Sicht der Erklärung ab, sondern den ganzen Umfang.

    Der compiler beschwert sich, weil die Zuordnung zu postParent ist außerhalb Ihrer Reichweite (die nur die geschachtelte Klammern). Wenn Sie versucht haben, deklarieren Sie eine neue variable an der Stelle, wo Sie gerade die Zuordnung zu postParent wäre das problem mit dem verschachtelten block, weil der Umfang der postParent würde gehören, dass der verschachtelte block, obwohl es schon vor der Erklärung.

    Bereiche sind beschrieben in Abschnitt 3.7 der C# – 3.0-Spezifikation.

    EDIT: Um auf Ihre Frage Antworten Bearbeiten.

    Es nur zwei einfache Regeln:

    • Sie kann nicht deklarieren Sie eine lokale variable, wenn eine lokale variable mit dem gleichen Namen in Reichweite
    • der Gültigkeitsbereich einer lokalen Variablen ist der block, in dem die Erklärung erfolgt

    Ich bin mir sicher, dass Sie die Sprache konnte wurden so konstruiert, dass der Umfang begann erst an dem Punkt der Erklärung, aber ich denke, es ist einfacher (in Bezug auf Sprache, Komplexität) zu berücksichtigen Bereiche als nur blocks – also alle lokalen Variablen, die in dem gleichen block haben die gleiche Bedeutung, zum Beispiel. Das macht das Leben viel einfacher, wenn man bedenkt erfassten Variablen auch – wie das, was eingefangen wird, hängt vom Umfang und geschachtelte scopes machen das Leben interessant…

    EDIT: die Sprache, Die Skillung hat dies zu sagen über die ursprüngliche lambda-Ausdruck Beispiel – es ist Abschnitt 7.14.1:

    Dem optionalen
    anonym-Funktion-Signatur einer
    anonyme Funktion definiert den Namen
    und Optional die Typen der formalen
    Parameter für die anonyme Funktion.
    Der Umfang der Parameter des
    die anonyme Funktion ist die
    anonym-Funktion-Körper. Zusammen mit
    der parameter-Liste (falls gegeben), der
    anonymous-Methode-Körper stellt eine
    Erklärung Raum. Aus diesem Grund
    ist eine compile-Zeit-Fehler für den Namen
    ein parameter, der die anonyme
    Funktion mit dem Namen einer lokalen
    variable, lokale Konstanten oder parameter
    dessen Geltungsbereich umfasst die
    anonymous-Methode-Ausdruck oder
    lambda-Ausdruck.

    Hilft das?

    • Unabhängig davon, ob das ist, warum es erzwingt, dass die Regel, die ich immer noch glaube, das ist ein Mangel, der in der CLR. Anonyme Methoden sollten auf jeden Fall descope Variablen erstellt, die innerhalb Sie aus einer anderen Funktion, auch es ist so einfach wie die CLR hinzufügen eines Präfixes zu jeder Variablen in der delegate-Methode.
    • Die CLR ist nicht beteiligt, an alle hier. Es ist eine Sprache, die Entscheidung. Und ich Stimme nicht ganz. Der Punkt ist, dass die äußeren Variablen sind verfügbar, um die anonyme Funktion, also die anonyme Funktion lässt sich nicht neu definieren Sie, in genau der gleichen Weise, wie wenn die Variablen wurden erneut deklariert in einem „normalen“ block.
    • Macht Sinn, da unter der Annahme der Erklärung ist Teil des ganzen Umfangs-block-Sie hätte keine Möglichkeit zu wissen, wenn die äußere variable sollte gerollt werden, in die anonyme Funktion oder nicht. Wenn es wurde, basierend auf, wo die variable den Gültigkeitsbereich von Ihnen könnte dies ermöglichen.
    • Ich aggree, dass es macht das Leben einfacher…aber es wäre schön, wenn die symantics wie eine variable verwendet wird, entspricht dem Umfang. Ich fand gerade diese Art von interessant, und jetzt, dass ich mit lambda-Ausdruck ist eine Menge in dieser (vor allem in meinem throw-away-prototype-code, wo ich manchmal faul und verwenden i, t..
    • Und warum sollten Sie nicht in der Lage sein, neu zu definieren die variable? Sie können ausblenden von Variablen mit der schlechten Programmierung in Klassen. Deklarieren Sie eine member-variable, und dann innerhalb einer Methode deklarieren Sie eine variable mit dem gleichen Namen und der compiler kümmert sich nicht. Es sollten die gleichen sein hier.
    • Ich bin nicht einverstanden mit der Sprache Spezifikation Durchsetzung der Regeln über die geplanten Praxis-wie das Erfordernis case-Anweisungen zu Bremsen. Fall fallen, durch die zugelassen werden sollten, und eine Warnung gegeben, nicht einen compile-Fehler. Dies ist die gleiche situation, und Sie sind sehr nitpicky mehr als ich, sagte CLR früher.
    • Chris: ich denke, wir müssen Zustimmen, nicht einverstanden sind. Ich mag die Art, wie die Sprache funktioniert für switch/case auch. (Es gibt immer springen, wenn Sie wirklich wollen, um…) (Und ich durchaus bestreiten, dass es nitpicky zu unterscheiden zwischen der Laufzeit und der Sprache. Es ist ein sehr wichtiger Unterschied.)
    • Ich glaube nicht, dass scope ist das Problem hier. Die Frage ist, warum der C# – compiler nicht lassen, Sie deklarieren eine variable mit dem gleichen Namen, wie ein Kind vor Umfang. In diesem Beispiel „st“ erklärt wird, in der untergeordneten lambda-Bereich – es ist nicht mehr im Gültigkeitsbereich der Zeit, in der Sie deklariert ist über ’string st = „warum das nicht?“;‘ Es gibt keine Sprache, die Grund – es muss sein, damit der Programmierer es vermeiden, schwer zu debug-code.
    • Scope ist der Grund dafür, dass der compiler nicht lassen Sie es tun, aber du hast das problem falsch herum. Der Grund, den der compiler ausgibt, ein Fehler ist, dass die latter Zeichenfolge ist bereits in Reichweite, wenn der lambda Ausdruck versucht zu erklären, st als parameter den Namen. Ich wage zu behaupten, der Sprache arbeiten könnte, um ihn, aber es ist eine Wahl getroffen.
    • Könnte es sein, dass der compiler erzwingt Geltungsbereich diese Weise, weil Sie ist möglich, mit einem springen, um zu springen zurück über die Kind-Bereich? Im wesentlichen wird es das gleiche Problem wie die preParent Beispiel in diesem Fall.
    • Naja, der compiler erzwingt, was die Spezifikation vorschreibt. Ich denke, Sie würden vorschlagen, eine alternative für mich zu wissen, ob es sinnvoll ist 🙂

  2. -2

    Sind Sie eine variable deklarieren in einem begrenzten Umfang und zu versuchen, es außerhalb dieses Bereichs. Der compiler davon ausgegangen, dass Sie nicht wollen, Zugang zu es so Sie deklarieren eine variable mit dem gleichen Namen irgendwo anders in der Datei. Ihr versucht zu tun, die alten C-trick, vorausgesetzt die variable wird sofort live außerhalb des Geltungsbereichs. Zum Beispiel diese verwendet, um die Arbeit in älteren Versionen von C/C++, aber nicht mehr.

    for (int i=0; i<10; i++)
    {
        cout <<”In the loop i is “<< i << endl;
    }
    cout << outside of the loop i is  << i << endl; //this only compiles with old C/C++ compilers.
    • Jared ist nicht das, was ich versuche zu tun;-) C# lässt nicht zu, dass Sie deklarieren eine variable mit dem gleichen Namen, wenn die variable deklariert ist, in einen untergeordneten Bereich.

Kostenlose Online-Tests