Ich fand folgendes sehr merkwürdig. Andererseits habe ich hauptsächlich Verschlüsse in dynamischen Sprachen verwendet, die für den gleichen "Bug" nicht suspekt sein dürften. Das folgende macht den Compiler unglücklich:
%Vor%Es sagt:
Eine lokale Variable namens 'i' kann nicht sein in diesem Bereich erklärt, weil es würde "ich" eine andere Bedeutung geben, welches bereits in einem "Kind" verwendet wird Bereich, um etwas anderes zu bezeichnen
Das heißt also, dass Variablen, die innerhalb eines Delegates deklariert sind, den Gültigkeitsbereich der Funktion haben. Nicht genau das, was ich erwartet hätte. Ich habe nicht einmal versucht, die Funktion anzurufen. Zumindest hat Common Lisp eine Funktion, die besagt, dass eine Variable einen dynamischen Namen haben sollte, wenn sie wirklich lokal sein soll. Dies ist besonders wichtig beim Erstellen von Makros, die nicht undicht sind, aber auch so etwas wäre hier hilfreich.
Ich frage mich also, was andere Leute tun, um dieses Problem zu umgehen?
Um zu klären, suche ich nach einer Lösung, bei der die Variablen, die ich im delegete deklariere, nicht in Variablen eingreifen, die nach dem Delegaten deklariert sind. Und ich möchte weiterhin Variablen erfassen können, die vor dem Delegaten deklariert wurden.
Dies muss so sein, damit anonyme Methoden (und Lambdas) lokale Variablen und Parameter verwenden können, die in der containing-Methode enthalten sind.
Die Problemumgehungen verwenden entweder unterschiedliche Namen für die Variable oder erstellen eine normale Methode.
Die von einer anonymen Funktion erzeugte "Schließung" unterscheidet sich etwas von der in anderen dynamischen Sprachen erstellten (ich verwende Javascript als Beispiel).
%Vor%Dieser kleine Teil von Javascript wird 1 und dann 2 anzeigen. Die anonyme Funktion kann auf die Variable o1 zugreifen, weil sie in ihrer Gültigkeitsbereichskette vorhanden ist. Die anonyme Funktion hat jedoch einen völlig unabhängigen Bereich, in dem sie eine andere o1-Variable erstellen und damit alle weiteren in der Scope-Kette verstecken kann. Beachten Sie auch, dass alle Variablen in der gesamten Kette erhalten bleiben. Daher würde o2 weiterhin existieren und eine Objektreferenz enthalten, solange die fn-Variable die Funktionsreferenz enthält.
Vergleichen Sie nun mit anonymen Funktionen von C #: -
%Vor% In diesem Fall erzeugt die anonyme Funktion keinen wirklich unabhängigen Bereich, genauso wenig wie die Variablendeklaration in einem anderen funktionsfähigen {} Blockcode (wird in foreach
, if
usw. verwendet) / p>
Daher gelten die gleichen Regeln, Code außerhalb des Blocks kann nicht auf Variablen zugreifen, die innerhalb des Blocks deklariert sind, aber Sie können auch keinen Identifier verwenden.
Eine Closure wird erstellt, wenn die anonyme Funktion außerhalb der Funktion übergeben wird, in der sie erstellt wurde. Die Abweichung vom JavaScript-Beispiel besteht darin, dass nur die tatsächlich von der anonymen Funktion verwendeten Variablen beibehalten werden, also in diesem Fall das Objekt by o2 wird für GC verfügbar sein, sobald die Sache abgeschlossen ist,
Sie erhalten CS0136 auch aus folgendem Code:
%Vor%Der Umfang der 2. Deklaration von "i" ist eindeutig, Sprachen wie C ++ haben damit kein Rindfleisch. Aber die C # -Sprachdesigner entschieden, es zu verbieten. Würden Sie angesichts des obigen Ausschnitts immer noch denken, dass das eine schlechte Idee war? Werfen Sie eine Menge zusätzlichen Code ein, und Sie könnten diesen Code eine Weile anstarren und den Fehler nicht sehen.
Die Problemumgehung ist trivial und schmerzlos, nur mit einem anderen Variablennamen kommen.
Wenn ich mich richtig erinnere, erstellt der Compiler ein Klassenmitglied der externen Variablen, auf die in der anonymen Methode verwiesen wird, damit dies funktioniert.
Hier ist ein Workaround:
%Vor%Tatsächlich scheint der Fehler nichts mit anonymen Delegaten oder Lamda-Ausdrücken zu tun zu haben. Wenn Sie versuchen, das folgende Programm zu kompilieren ...
%Vor%... Sie erhalten genau den gleichen Fehler, egal ob Sie in der Zeile kommentieren oder nicht. Die Fehlerhilfe zeigt einen sehr ähnlichen Fall. Ich denke, es ist vernünftig, beide Fälle abzulehnen, weil die Programmierer die beiden Variablen verwechseln könnten.
Tags und Links c# lambda scope functional-programming delegates