2012-05-23 8 views
5

Ich habe diese Frage gelesen (What is the scope of a lambda variable in C#?)Warum Lambda-Variablenbereich außerhalb von LINQ Query existiert?

Aber es geht um Lambda Variable Bereich in LINQ-Abfrage.

Nun zu meiner Frage

Können sagen, ich habe eine sehr einfache LINQ-Abfrage.

var Foo = FoobBar.Select(x => x); 
var x = somefunction(); 

Compiler sagt: A local variable 'x' cannot be declared in this scope because it would give a different meaning to 'x', which is already used in a 'child' scope to denote something else.

Warum ist das so? Sollte die Variable Lambda nicht mehr existieren, wenn die LINQ-Abfrage endet?

EDIT: Nach dem Lesen der Antworten kam ich zu dem Ergebnis, dass es die Außenseite x (von der Funktion zurückgegeben), deren Bereich innerhalb LINQ Query erstreckt.

+1

Nach dem Lesen aller Antworten kam ich zu dem Schluss, dass es umgekehrt ist. Der Umfang der externen Variablen existiert in der LINQ-Abfrage. –

+1

Und andersherum auch ;-) Eine Sprache wäre nicht refactoring-freundlich, wenn sie den Code kompilieren ließe, nur weil die widersprüchliche Variable ('var x = somefunction();') in der zweiten Zeile steht und dann Sie bewegen die zweite Zeile in der ersten Zeile, sehr zu Ihrem Verdruss, würde es nicht mehr kompilieren. C# macht einen Präventivmechanismus, es erlaubt 'var x = someFunction()' nicht, selbst in der zweiten Zeile zu kompilieren, da Sie den Code jederzeit neu Faktorisieren und später in die erste Zeile setzen können. Wir leben in einem Alter, in dem ein Refactoring-zugänglicher Code die Norm ist –

Antwort

9

Es geht nicht um LINQ, es geht um untergeordnete Bereiche.

Zum Beispiel:

foreach (var bar in FooBar.Bars) 
     { 
      var x = FooBar.GetFoo(); 
     } 
var x = new Foo(); 

erzeugt genau die gleiche Fehlermeldung von Compiler.

Um das zu beheben, müssen Sie nur Variablen in verschiedenen (nicht verschachtelten) Bereichen platzieren. Beispiel:

foreach (var bar in FooBar.Bars) 
     { 
      var x = FooBar.GetBar(); 
     } 
{ 
    var x = new Foo(); 
} 
4

Lets genau hinschauen,

var Foo = FoobBar.Select(x => x); 

wahr der Umfang der x im Ausdruck

var x = somefunction() 

Jetzt endet das interessant ist, diese für das gesamte Verfahren scoped ist, die zu dem lamda Ausdruck gilt, daher kann der Compiler nicht unterscheiden, da der Bereich des letzteren den ersten überlappt. und sehr informative Nachricht zu eine andere Bedeutung geben zu ‚x‘, die bereits in einem ‚Kind‘ verwendet Umfang(Wählen Sie, wie in Ihrem Fall)

Similar scope question

vielleicht können Sie Klammern umfassen um der andere so, dass es den Umfang

definiert ist
{ 
var x = somefunction() 
} 
+0

Im letzten Ausschnitt bedeutet das, dass der Umfang von x innerhalb dieser geschweiften Klammern begrenzt ist? –

+0

@NikhilAgrawal ja – V4Vendetta

1

es ist nicht klar (für den Compiler), die ‚x‘ Sie durch die zweite ‚x‘ (nach dem =>) bedeuten.

Was ist, wenn Sie diese schreiben:

var Foo = FoobBar.Select(y => x); 
var x = somefunction(); 

dann, dass x im Lambda mit dem ‚Einefunktion‘ Ergebnis kollidieren würde.

1

Sie können nicht zwei Variablen mit demselben Namen im selben Bereich deklarieren.

„Same scope“ bedeutet, dass sie entweder sind beide innerhalb des aktuellen Bereichs

void method() 
{ 
    int a; 
    int a; //wrong! 
} 

oder ein in der aktuellen und der andere ist in einem Kind Umfang.

void method() 
{ 
    int a; 
    for(;;) 
    { 
     int a; //wrong again! 
    } 
} 

Das ist von Entwurf und gilt für jede Variable, von int s Lambda Referenzen.

2

denken, wenn C# diese beiden Variablen bestehen auf demselben Umfang Ebene erlauben würde, wird dies nicht möglich sein:

static void test() { 

    Action<int> x = (z) => { 
     Console.WriteLine(z);    
    }; 


    int[] i = { 5,2,0,1,3,1,4 }; 

    var kyrie = i.Select (x => x); 

} 

Wie würden Sie zu C# sagen, dass Sie die Aktionsdelegate namens x zu kyrie zuweisen wollte Variable; oder umgekehrt, wie würdest du zu C# sagen, du wolltest die ganzzahlige Projektion selbst benutzen? Wie würde C# das auflösen?

Und C# Scoping-Auflösung ist sehr konsistent, ob Sie es vor der anderen Variablen oder nach den anderen Variablen deklarieren, sie sind identisch. z.B. http://www.anicehumble.com/2012/05/java-said-c-said-scope-consistency.html

jene Szenario eindeutig zu machen, ist C# nicht zulassen, dass Sie ein Programm kompilieren, die Variablennamen, die auf der gleichen Ebene existiert

Es geht um Ihre exprimierenden Absicht an den Compiler in einem nicht-mehrdeutig Weg. Und C# hat eine gute Arbeit in dieser Hinsicht

+0

+1 für "Es geht darum, Ihre Absicht auf eine eindeutige Weise zum Compiler auszudrücken". Genau richtig. –