2012-05-23 4 views
5

Przeczytałem to pytanie (What is the scope of a lambda variable in C#?)Dlaczego zakres zmienny Lambda istnieje poza zapytaniem LINQ?

Ale chodzi o zakres zmienny Lambda wewnątrz kwerendy LINQ.

Teraz moje pytanie

Powiedzmy mam bardzo prostej kwerendy LINQ.

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

Kompilator mówi: 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.

Dlaczego tak jest? Czy zmienna Lambda nie powinna przestać istnieć po zakończeniu zapytania LINQ?

EDYCJA: Po przeczytaniu odpowiedzi doszedłem do wniosku, że jest to zewnętrzna strona x (zwrócona z funkcji), której zakres obejmuje wewnątrz zapytania LINQ.

+1

Po przeczytaniu wszystkich odpowiedzi doszedłem do wniosku, że jest odwrotnie. zakres zmiennej zewnętrznej istnieje wewnątrz kwerendy LINQ. –

+1

I na odwrót ;-) Język nie byłby przyjazny dla refaktoryzacji, gdyby pozwolił kodowi skompilować tylko dlatego, że zmienna powodująca konflikt ('var x = somefunction();) jest w drugiej linii, a następnie gdy przesuwasz drugą linię w pierwszej linii, ku swojemu rozczarowaniu, nie skompilowałaby się więcej. C# działa z mechanizmem zapobiegawczym, nie pozwala na 'var x = someFunction()' do kompilowania nawet w drugim wierszu, ponieważ możesz ponownie zaimplementować swój kod w dowolnym momencie i umieścić go w pierwszej linii później. Żyjemy w epoce, w której kod refaktoryzujący się jest normą –

Odpowiedz

9

Tu nie chodzi o LINQ, chodzi o zakresy dla dzieci.

Na przykład:

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

produkuje dokładnie ten sam komunikat o błędzie od kompilatora.

Aby to naprawić, wystarczy umieścić zmienne w różnych (nie zagnieżdżających) zakresach. Na przykład:

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

Spójrzmy uważnie,

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

prawdziwy zakres X kończy się wyrażeniem

var x = somefunction() 

Teraz to jest interesujące, to jest zawężona do całego sposobu, który posiada wyrażenie lambda też więc kompilator nie może odróżnić, ponieważ zakres tego ostatniego pokrywa się z pierwszym. i wiadomość bardzo pouczające zbyt nadać inny sens „x”, który jest już stosowany w ramach danej „dziecko”(wybrać w Twoim przypadku)

Similar scope question

może można dołączyć nawiasy wokół drugą tak, że jest to zakres jest określony

{ 
var x = somefunction() 
} 
+0

W ostatnim fragmencie oznacza to, że zakres x jest ograniczony wewnątrz tych nawiasów klamrowych? –

+0

@NikhilAgrawal yes – V4Vendetta

1

nie jest jasne (do kompilatora), który „x” masz na myśli drugi „x” (po =>).

Co jeśli napisał to:

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

wtedy x w lambda będzie kolidować z 'someFunction' wynik.

1

Nie można zadeklarować dwóch zmiennych o tej samej nazwie w tym samym zakresie.

„sam zakres”, co oznacza, że ​​albo są zarówno wewnątrz bieżącego zakresu

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

lub jeden jest w prąd, a druga jest w zasięgu dzieci.

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

Jest to zgodne z projektem i zachodzi dla dowolnej zmiennej, od int s do referencji lambda.

2

Pomyśl czy C# pozwoliłaby te dwie zmienne istnieć na tym samym poziomie zakresu, to nie będzie możliwe:

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); 

} 

Jak byś powiedział do C#, który chcesz przypisać delegata działania o nazwie x Kyrie zmienna; lub odwrotnie, w jaki sposób powiedziałbyś C#, że chcesz użyć samej projekcji całkowitej? Jak C# to rozwiązałoby?

Rozdzielczość w skali C# jest bardzo spójna niezależnie od tego, czy zadeklarowano ją przed inną zmienną, czy po innych zmiennych, są one takie same. na przykład http://www.anicehumble.com/2012/05/java-said-c-said-scope-consistency.html

disambiguate te scenariusz, C# nie pozwalają na kompilacji programu, które mają nazwy zmiennych, które istnieje na tym samym poziomie

Chodzi o wyrażanie swoich intencją do kompilatora w sposób non-niejednoznaczne sposób. A C# wykonał dobrą robotę pod tym względem

+0

+1 dla "Chodzi o wyrażenie zamiaru kompilatorowi w sposób niejednoznaczny". Dokładnie tak. –