2012-05-23 11 views
5

Leí esta pregunta (What is the scope of a lambda variable in C#?)¿Por qué existe el ámbito variable Lambda fuera de LINQ Query?

Pero se trata del alcance variable de Lambda dentro de LINQ Query.

Ahora a mi pregunta

Digamos que tengo una consulta LINQ muy simple.

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

Compiler dice: 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.

¿Por qué es así? ¿La variable Lambda no debería dejar de existir cuando termina la consulta LINQ?

EDIT: Después de leer las respuestas llegué a la conclusión de que es el exterior x (devuelto desde la función) cuyo alcance se extiende dentro de LINQ Query.

+1

Después de leer todas las respuestas llegué a la conclusión de que es al revés. el alcance de la variable externa existe dentro de la consulta LINQ. –

+1

Y a la inversa también ;-) Un lenguaje no sería fácil de refactorizar si permitía compilar el código solo porque la variable en conflicto ('var x = somefunction();') está en la segunda línea, y luego cuando Mueves la segunda línea en la primera línea, para tu disgusto, ya no compilaría. C# tiene un mecanismo preventivo, no permite que 'var x = someFunction()' compile, incluso está en la segunda línea, ya que puede volver a factorizar el código en cualquier momento y ponerlo en la primera línea más adelante. Estamos viviendo en una era en la que un código susceptible de refactorización es la norma –

Respuesta

9

No se trata de LINQ, se trata de alcances para niños.

Por ejemplo:

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

produce exactamente el mismo mensaje de error del compilador.

Para solucionarlo, solo tiene que colocar variables en ámbitos diferentes (no anidables). Por ejemplo:

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

Veamos con cuidado,

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

verdadera del alcance de x termina en la expresión

var x = somefunction() 

Ahora esto es interesante, esto está en el ámbito de todo el método que mantiene la expresión lambda también, por lo que el compilador no puede distinguir ya que el alcance de este último se superpone al primero. y el mensaje muy informativo también dar un significado diferente a 'x', que ya se utiliza en el ámbito de un 'niño'(Seleccione como en su caso)

Similar scope question

tal vez usted puede incluir apoyos en torno la otra para que sea alcance está definido

{ 
var x = somefunction() 
} 
+0

En el último fragmento, ¿significa que el alcance de x está limitado dentro de esas llaves? –

+0

@NikhilAgrawal yes – V4Vendetta

1

no está claro (al compilador), que 'x' se refiere con el segundo 'x' (después de la =>).

¿Qué pasa si usted escribió esto:

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

entonces que x en el lambda chocarían con el resultado 'algunaFuncion'.

1

No puede declarar dos variables con el mismo nombre en el mismo ámbito.

"mismo alcance", que significa que o bien son tanto dentro del ámbito actual

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

o uno está en la corriente y el otro es en un ámbito secundario.

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

Esto es por diseño y es válido para cualquier variable, desde int s de referencias lambda.

2

Piense si C# permitiría a esas dos variables que existen en el mismo nivel de ámbito, esto no será posible:

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

} 

¿Cómo le diría a C# que usted quiere asignar el delegado de Acción llamada x a Kyrie variable; o viceversa, ¿cómo le dirías a C# que querías usar la proyección entera en sí? ¿Cómo C resolvería eso?

Y la resolución del alcance de C# es muy uniforme, ya sea que la declare antes que la otra variable o después de las otras variables, son las mismas. p.ej. http://www.anicehumble.com/2012/05/java-said-c-said-scope-consistency.html

para eliminar la ambigüedad aquellos escenario, C# no permite compilar un programa que tiene los nombres de variables que existe en el mismo nivel

Se trata de expresar su intención al compilador de una forma no ambigua forma. Y C# hizo un buen trabajo en ese sentido

+0

+1 para "Se trata de expresar su intención al compilador de una manera no ambigua". Exactamente correcto. –

Cuestiones relacionadas