Ceci est une extension de la question de l' accès à la fermeture modifiée . Je veux juste vérifier si ce qui suit est réellement suffisamment sûr pour une utilisation en production.
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); });
}
Je n'exécute ce qui précède qu'une fois par démarrage. Pour l'instant, cela semble bien fonctionner. Comme Jon l'a mentionné à propos du résultat contre-intuitif dans certains cas. Alors, que dois-je faire attention ici? Est-ce que ça ira si la liste est parcourue plus d'une fois?
Réponses:
Avant C # 5, vous devez re-déclarer une variable à l' intérieur du foreach - sinon, elle est partagée et tous vos gestionnaires utiliseront la dernière chaîne:
De manière significative, notez qu'à partir de C # 5, cela a changé, et en particulier dans le cas de
foreach
, vous n'avez plus besoin de le faire: le code de la question fonctionnerait comme prévu.Pour montrer que cela ne fonctionne pas sans cette modification, tenez compte des éléments suivants:
Exécutez ce qui précède avant C # 5 , et bien que chaque bouton affiche un nom différent, cliquez sur les boutons pour afficher «Wilma» quatre fois.
En effet, la spécification du langage (ECMA 334 v4, 15.8.4) (avant C # 5) définit:
Notez que la variable
v
(qui est la vôtrelist
) est déclarée en dehors de la boucle. Ainsi, selon les règles des variables capturées, toutes les itérations de la liste partageront le détenteur de la variable capturée.À partir de C # 5, cela est changé: la variable d'itération (
v
) est portée à l' intérieur de la boucle. Je n'ai pas de référence de spécification, mais cela devient essentiellement:Re désabonnement; si vous souhaitez activement désinscrire un gestionnaire anonyme, l'astuce consiste à capturer le gestionnaire lui-même:
De même, si vous voulez un gestionnaire d'événements unique (tel que Load, etc.):
Ceci est maintenant auto-désabonnement ;-p
la source
for
inchangé dans 5.0