tutorial expressions expresiones c# lambda scope

expresiones - lambda expressions c#



¿Cuál es el alcance de una variable lambda en C#? (8)

C # no admite el sombreado de esa manera.

La razón por la cual o1 funciona nuevamente es porque no o1 el o1 anterior.

Estoy confundido sobre el alcance de la variable lambda, tome por ejemplo lo siguiente

var query = from customer in clist from order in olist .Where(o => o.CustomerID == customer.CustomerID && o.OrderDate == // line 1 olist.Where(o1 => o1.CustomerID == customer.CustomerID) // line 2 .Max(o1 => o1.OrderDate) // line 3 ) select new { customer.CustomerID, customer.Name, customer.Address, order.Product, order.OrderDate };

En la línea 1, he declarado una variable lambda ''o'', lo que significa que no puedo volver a declararla en la línea 2 (o al menos el compilador se queja si intento) pero no se queja de la línea 3 aunque ''o1'' ya existe ??

¿Cuál es el alcance de una variable lambda?


El alcance de un parámetro lambda es igual al alcance completo del cuerpo de la expresión lambda, incluidas las expresiones o ámbitos internos de lambda.

Si ampliamos la sintaxis de sus expresiones lambda y agregamos alguna sangría amiga, puede volverse más clara (¡aunque probablemente en ninguna parte tan clara como la respuesta diagramática de yamen !):

.Where(o => { return o.CustomerID == customer.CustomerID && o.OrderDate == olist.Where( o1 => o1.CustomerID == customer.CustomerID ) .Max( o1 => o1.OrderDate ); })

Observe que su .Where().Max() se encuentra dentro de un .Where() externo. La o en la lambda externa está encapsulada por la lambda externa dentro de su lambdas interno (esto se llama cierre ) de modo que ya existe en el alcance de su lambdas interno, y no puede reutilizarse como parámetro.

Puedes reutilizar o1 porque tus dos lambdas internas están completamente separadas una de otra, por lo que no viven más allá del alcance de ninguna de ellas.


Es lo mismo que con cualquier otra variable. El alcance de o es la expresión completa en su primer Where , por lo que no puede usarlo nuevamente en el segundo, que está dentro del primero. Pero el alcance de o1 es solo la expresión en su segundo Where , por lo que puede usarlo en la expresión de su Max , que está fuera del segundo Where . En el código:

// o scope lasts until the first bracket is closed Where(o => o.CustomerID == customer.CustomerID && o.OrderDate == // o1 scope lasts until the second bracket is closed; the first is not yet closed here olist.Where(o1 => o1.CustomerID == customer.CustomerID) // The second bracket is closed, so o1 is already out of scope; o is still in scope .Max(o1 => o1.OrderDate) ) // The first bracket is closed, so o is finally out of scope


Intento imaginarlo así según tu código ...

.Where(o => o.CustomerID == customer.CustomerID && o.OrderDate == // line 1 olist.Where(o1 => o1.CustomerID == customer.CustomerID) // line 2 .Max(o1 => o1.OrderDate) // line 3 )

Una forma bastante tosca de explicar, pero sus corchetes determinan el alcance. Tu segundo o1 no está anidado dentro del segundo, de otra forma tendrías el mismo problema

//outermost where ((BEGIN-o //inner where (BEGIN-o1 END-o1) //max (BEGIN-o1 END-o1) END-o))


Los corchetes dan la clave: la variable lambda se captura en el ámbito de su declaración:

.Where(o => ... olist.Where(o1 => ...).Max(o1 => ...)) // |----------------------------------------------| scope of o // |---------| scope of first o1 // |---------| scope of second o1

Tenga en cuenta que no hay superposición para las dos variables o1 , pero ambas se superponen (o sombrean) la variable o y, por lo tanto, no pueden usar el mismo nombre.


No puede usar el mismo nombre de variable en dos ámbitos si uno de los ámbitos contiene el otro.

En su pregunta, o se introduce en el ámbito externo, por lo que no se puede usar nuevamente en el segundo Where() o en Max() , porque estos ámbitos están contenidos en el exterior.

Por otro lado, puede usar o1 en ambos ámbitos internos porque uno no contiene el otro, por lo que no hay ambigüedad allí.


porque el lamda es el reemplazo de la función anónima aquí en tu código

Mismo alcance

Where(o => o.CustomerID == customer.CustomerID && o.OrderDate == //line 1 olist.Where(o1 => o1.CustomerID == customer.CustomerID) //line 2

es el alcance de la función en la cual varialble "o" live

aquí, en la línea tres, esta es una nueva pérdida de la variable, es decir, un nuevo alcance funcional

Alcance diferente

.Max(o1 => o1.OrderDate) ) //line 3

entonces el reson en la línea 1 y la línea 2 varialbe "o" definido en la línea 1 no se puede definir en la línea 2 debido a la misma scrop y la definición "o1" en la línea 2 se puede definir nuevamente en la línea 3 porque está en un alcance de función diferente


var external = 1; //This is a scope Action scope = new Action(() => { //myVar is not accessible from outside var myVar = 0 + external; Console.WriteLine(myVar); //outputs 1 }); //Call the scope scope(); //Console.WriteLine(myVar);//Will not compile

Cuando se compila el código, toda la lógica del vacío declarado en la acción ()=>{ ... } moverá a un método en el tipo con un nombre destrozado.

El tiempo de ejecución llamará a la función recién creada cuando llegue a ese lugar en la pila.

Puede pasar valores a un alcance / lambda de varias maneras, que es lo mismo para sacarlos.

Las variables declaradas en una lambda no son accesibles afuera con su nombre declarado.

También es posible utilizar el reflejo para extraer el nombre destrozado, pero no estoy seguro de que lo requiera. (Por favor, avíseme si me equivoco).