tutorial expressions expresiones ejemplos c# .net c#-4.0 lambda scope

c# - expressions - Clarificación del alcance de Lambda



linq lambda c# tutorial (3)

¿Por qué mi parámetro x comporta de manera errática?

  1. Ejemplo 1 - No existe en el contexto actual.
  2. Ejemplo 2: No se puede reutilizar x porque está definido en un ámbito "secundario".
  3. Ejemplo 3 - Bien. Esta es la parte en la que estoy confundido. Tal vez un alcance ''infantil'' diferente?

Ejemplo 1 :

List<int> list = new List<int> { 1, 2, 3, 4, 5 }; var result = list.Where(x => x < 3); Console.Write(result.ElementAt(x));

crea este error de tiempo de compilación:

El nombre ''x'' no existe en el contexto actual

lo cual espero

Ejemplo 2 :

List<int> list = new List<int> { 1, 2, 3, 4, 5 }; var result = list.Where(x => x < 3); int x = 1; Console.Write(result.ElementAt(x));

produce este error en tiempo de compilación:

Una variable local llamada ''x'' no se puede declarar en este ámbito porque daría un significado diferente a ''x'', que ya se usa en un alcance ''secundario'' para denotar algo más

Entiendo el alcance como se responde en esta pregunta, ¿hay alguna razón para que C # reutilice la variable en un foreach? . Sin embargo, esto es algo que nunca he visto antes. Además, responde a esta pregunta: ¿Cuál es el alcance de una variable lambda en C #? incompleto o incorrecto

Ejemplo 3 :

List<int> list = new List<int> { 1, 2, 3, 4, 5 }; List<string> stringList = new List<string> { "A", "B" }; var result = list.Where(x => x < 3); var result2 = stringList.Where(x => x != "A"); Console.Write(result2);

No hay errores producidos.

Con la respuesta aceptada, estas publicaciones de blog de Eric Lippert me ayudaron a entender lo que estaba sucediendo. Si alguien todavía está confundido:

espacio de declaración

nombres simples


Los ámbitos secundarios (ejemplo 3) pueden usar las mismas variables, pero padres e hijos no pueden volver a declarar las variables.

Puedes obtener lo mismo con por:

// Child scopes for (int i = 1; i < 10; i++){ /* do something */ } for (int i = 1; i < 10; i++){ /* do something else */ }

Esto fallaría:

// Child and parent for (int i = 1; i < 10; i++){ /* do something */ } int i = 33;


No es tan complicado como parece ser.

Si define un parámetro para una expresión lamda, el parámetro solo es válido dentro del alcance de la expresión lamda

(int x) => { //x is only valid inside this scope }

Si tiene una segunda variable con el definido en el mismo ámbito que la expresión lamda, obtendrá un error, porque esta segunda variable también es válida en el ámbito de la expresión lamda.

void Foo() { int y; //y is valis in the scope of foo (int x) => { //x is only valid inside this scope //y is valid in the scope of foo and the lamda expression } }

En el tercer ejemplo, tienes 2 diferentes expresiones de lamda y, por lo tanto, dos ámbitos diferentes


En el Example 1 , x se define en el ámbito local de la expresión lamdba y no es visible en la tercera línea

En el Example 2 , ahora ha declarado dos variables llamadas "x" en el mismo ámbito de declaración (la visibilidad es diferente)

Con un método lambda o anónimo, "captura" el ámbito en el que se ejecuta. Si tiene una x local en el mismo ámbito que la definición lambda, entonces "captura" esa x para obtener lo que la lambda puede acceder, lo que da como resultado dos definiciones de "x". Lo que declaras en la lambda no se captura en la otra dirección, por lo que no es visible fuera de la lambda.

En el Example 3 , ahora no está utilizando una variable que es local solamente la lambda fuera de la lambda, y no nombra algo igual en el mismo ámbito de declaración.