Fermeture capturée (variable de boucle) en C # 5.0

Cela fonctionne très bien (signifie comme prévu) en C # 5.0:

var actions = new List(); foreach (var i in Enumerable.Range(0, 10)) { actions.Add(() => Console.WriteLine(i)); } foreach (var act in actions) act(); 

Imprime de 0 à 9. Mais celui-ci affiche 10 fois 10 fois:

 var actions = new List(); for (var i = 0; i  Console.WriteLine(i)); } foreach (var act in actions) act(); 

Question: C’était un problème que nous avions dans les versions C # avant la version 5.0; Nous avons donc dû utiliser un espace réservé local pour la fermeture et il est maintenant corrigé – en C # 5.0 – dans les boucles “foreach”. Mais pas dans les boucles “for”!

Quel est le raisonnement derrière cela (ne pas régler le problème for boucles aussi)?

Quel est le raisonnement derrière cela?

Je vais supposer que vous voulez dire “pourquoi n’a-t-il pas changé for boucles aussi?”

La réponse est que, pour les boucles, le comportement existant est parfaitement logique. Si vous cassez une boucle en:

  • initialiseur
  • condition
  • iterator
  • corps

… alors la boucle est grosso modo:

 { initializer; while (condition) { body; iterator; } } 

(Sauf que l’ iterator est également exécuté à la fin d’une instruction continue; .)

La partie d’initialisation ne se passe logiquement qu’une fois, il est donc tout à fait logique qu’il n’y ait qu’une seule “instanciation de variable”. De plus, il n’y a pas de valeur “initiale” naturelle de la variable à chaque itération de la boucle – il n’y a rien à dire qu’une boucle for doit être d’une forme déclarant une variable dans l’initialiseur, la tester dans la condition et la modifier iterator Qu’attendriez-vous d’une boucle comme celle-ci:

 for (int i = 0, j = 10; i < j; i++) { if (someCondition) { j++; } actions.Add(() => Console.WriteLine(i, j)); } 

Comparez cela avec une boucle foreach qui ressemble à une déclaration séparée pour chaque itération. Heck, la variable est en lecture seule, ce qui rend encore plus étrange de penser qu’elle est une variable qui change entre les itérations. Il est parfaitement logique de considérer une boucle foreach comme déclarant une nouvelle variable en lecture seule sur chaque itération avec sa valeur extraite de l’iterator.