2011-05-27 23 views
6

He siguiente fragmento de código en C#Una variable local no se puede declarar en este ámbito [expresión LINQ/Lambda]

static void Main() 
{ 
    var numbers = new[] { 1, 2, 3, 4, 5, 6 }; 

    var ngt5 = numbers.Where(n => n > 5); 

    var n = ngt5.First().ToString(); 

    Console.WriteLine(n, numbers); 
} 

Cuando soy compilar el código anterior que estoy consiguiendo error siguiente

Un variable local llamada 'n' no se puede declarar en este ámbito

+2

¿Cuál es el contexto de este código? – SirPentor

+0

@Tobias: He modificado mi código –

Respuesta

16

Su problema está aquí:

// Within your lambda you have an 'n'. 
var ngt5 = numbers.Where(n => n > 5); 

// And within the outer scope you also have an 'n'. 
var n = ngt5.First().ToString(); 

Para entender por qué esto es un problema, considere el siguiente código:

int n = 1000; 
var evens = Enumerable.Range(1, 1000).Where(n => n % 2 == 0); 

La expresión n % 2 == 0 anterior es ambigua: el que n estamos hablando? Si estamos hablando de la exteriorn, entonces n % 2 == 0 es siempre cierto, ya que es sólo n 1000 (y por lo tanto evens comprenderá todos los números del 1 al 1000). Por otro lado, si estamos hablando de innern, entonces n % 2 == 0 solo será válido para valores pares de n (y evens serán 2, 4, 6, ... 1000).

El punto importante a tener en cuenta es que las variables declaradas fuera de lambda son accesibles desde el alcance de lambda.

int n = 0; 
Action incrementN =() => n++; // accessing an outer variable 
incrementN(); 
Console.WriteLine(n); // outputs '1' 

Esto es por qué existe la ambigüedad, y por lo tanto no está permitido.


La solución es simplemente elegir un nombre de variable diferente para su lambda; e.g .:

var ngt5 = numbers.Where(x => x > 5); 
+0

@Dan: ¿quiere decir que la variable lambda es global? –

+1

@geek: No, no es global. Voy a actualizar mi respuesta para explicar mejor ... –

+0

@Dan Tao: Ok señor –

0

Su problema es que supone que los cierres son funciones de primera clase en C#, que no es el caso y ojalá fuera el caso.

No se puede tratar el alcance del cierre C# como ámbito de función aislado.

No se puede devolver la expresión de Linq complicada fuera del alcance actual.

JavaScript permite esta ambigüedad, que permite escribir cierres sin límite, lo que hace que los cierres tengan funciones de primera clase de JavaScript.

Cuestiones relacionadas