Esta es una extensión de la pregunta de Acceso a Cierre Modificado . Solo quiero verificar si lo siguiente es realmente lo suficientemente seguro para su uso en producción.
List<string> lists = new List<string>();
//Code to retrieve lists from DB
foreach (string list in lists)
{
Button btn = new Button();
btn.Click += new EventHandler(delegate { MessageBox.Show(list); });
}
Solo ejecuto lo anterior una vez por inicio. Por ahora parece funcionar bien. Como Jon ha mencionado sobre el resultado contradictorio en algún caso. Entonces, ¿qué debo tener cuidado aquí? ¿Estará bien si la lista se revisa más de una vez?
Respuestas:
Antes de C # 5, debe volver a declarar una variable dentro de foreach; de lo contrario, se comparte y todos sus controladores usarán la última cadena:
Significativamente, tenga en cuenta que desde C # 5 en adelante, esto ha cambiado, y específicamente en el caso de
foreach
, ya no necesita hacer esto: el código en la pregunta funcionaría como se esperaba.Para mostrar que esto no funciona sin este cambio, considere lo siguiente:
Ejecute lo anterior antes de C # 5 , y aunque cada botón muestra un nombre diferente, al hacer clic en los botones se muestra "Wilma" cuatro veces.
Esto se debe a que la especificación de lenguaje (ECMA 334 v4, 15.8.4) (antes de C # 5) define:
Tenga en cuenta que la variable
v
(que es sulist
) se declara fuera del ciclo. Entonces, según las reglas de las variables capturadas, todas las iteraciones de la lista compartirán el titular de la variable capturada.Desde C # 5 en adelante, esto se cambia: la variable de iteración (
v
) tiene un alcance dentro del ciclo. No tengo una referencia de especificación, pero básicamente se convierte en:Volver a cancelar la suscripción; Si desea cancelar activamente la suscripción de un controlador anónimo, el truco consiste en capturar el controlador en sí:
Del mismo modo, si desea un controlador de eventos único (como Load, etc.):
Esto ahora es auto-cancelación de suscripción ;-p
fuente
for
ha cambiado en 5.0