tutorial sintaxis query espaƱol c# linq

c# - sintaxis - linq>#



Trampa de Variable Exterior (5)

@dtb es correcto (gran +1), pero es importante tener en cuenta que esto solo se aplica si el alcance del cierre se extiende fuera del ciclo. Por ejemplo:

var objects = new [] { new { Name = "Bill", Id = 1 }, new { Name = "Bob", Id = 5 }, new { Name = "David", Id = 9 } }; for (var i = 0; i < 10; i++) { var match = objects.SingleOrDefault(x => x.Id == i); if (match != null) { Console.WriteLine("i: {0} match: {1}", i, match.Name); } }

Esto se imprimirá:

i: 1 match: Bill i: 5 match: Bob i: 9 match: David

ReSharper advertirá sobre "Acceso al cierre modificado", que puede ignorarse de forma segura en este caso.

¿Qué es exactamente la trampa de la variable externa? Explicación y ejemplos en C # son apreciados.

EDITAR: Incorporando el diktat de Jon Skeet :)

Eric Lippert en la trampa de la variable exterior


Algo como

foreach (var s in strings) var x = results.Where(r => (r.Text).Contains(s));

No dará los resultados que espera porque los Contiene no se ejecutan para cada iteración. Sin embargo, la asignación de s a una variable temporal dentro del ciclo solucionará esto.



La "Trampa de Variable Externa" ocurre cuando un desarrollador espera que el valor de una variable sea capturado por una expresión lambda o un delegado anónimo, cuando en realidad la variable se captura por sí misma.

Ejemplo:

var actions = new List<Action>(); for (var i = 0; i < 10; i++) { actions.Add(() => Console.Write("{0} ", i)); } foreach (var action in actions) { action(); }

Posible resultado n. ° 1:

0 1 2 3 4 5 6 7 8 9

Posible resultado n. ° 2:

10 10 10 10 10 10 10 10 10 10

Si esperaba la salida n. ° 1, ha caído en la trampa de la variable externa. Obtienes la salida n. ° 2.

Fijar:

Declara una "variable interna" que se capturará repetidamente en lugar de la "variable externa" que se captura solo una vez.

var actions = new List<Action>(); for (var i = 0; i < 10; i++) { var j = i; actions.Add(() => Console.Write("{0} ", j)); } foreach (var action in actions) { action(); }

Para más detalles, ver también el blog de Eric Lippert .


Vale la pena observar que esta trampa también existió para los bucles foreach pero se modificó desde C # 5.0, es decir, que los cierres de bucles foreach ahora se cierran sobre una nueva copia de la variable de bucle cada vez. Entonces el siguiente código:

var values = new List<int>() { 100, 110, 120 }; var funcs = new List<Func<int>>(); foreach (var v in values) funcs.Add(() => v); foreach (var f in funcs) Console.WriteLine(f());

Imprime 120 120 120 <C # 5.0 , pero 100 110 120 > = C # 5.0

Sin embargo, los bucles aún se comportan de la misma manera.