55 votes

Pourquoi est-il mauvais d'utiliser une variable d'itération dans une expression lambda

J'écrivais un code rapide et j'ai remarqué cette erreur.

L'utilisation de la variable d'itération dans une expression lambda peut avoir des résultats inattendus.
Au lieu de cela, créez une variable locale dans la boucle et attribuez-lui la valeur de la variable d'itération.

Je sais ce que cela signifie et je peux facilement le réparer, ce n'est pas grave.
Mais je me demandais pourquoi utiliser une variable d'itération dans un lambda est une mauvaise idée.
Quels problèmes puis-je causer plus tard?

56voto

Jon Skeet Points 692016

Considérer ce code:

List<Action> actions = new List<Action>();

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

foreach (Action action in actions)
{
    action();
}

Qu'attendez-vous cette impression? La réponse évidente est de 0...9 - mais en réalité, il imprime 10, dix fois. C'est parce qu'il y a juste une variable qui est capturée par tous les délégués. C'est ce genre de comportement qui est inattendu.

EDIT: je viens de voir que vous parlez VB.NET plutôt que de C#. Je crois VB.NET a même des règles plus compliquées, en raison de la façon dont les variables de maintenir leurs valeurs à travers des itérations. Ce post par Jared Parsons donne quelques informations sur le type de difficultés rencontrées - même si il est de retour à partir de 2007, de sorte que le comportement réel peuvent avoir changé depuis.

8voto

Greg Beech Points 55270

En supposant que tu veux dire C# ici.

C'est à cause de la manière dont le compilateur met en œuvre des fermetures. À l'aide d'une variable d'itération peut provoquer un problème avec accès à une modification de la fermeture (notez que j'ai dit 'peut' pas 'sera' cause un problème, parce que parfois, il n'arrive pas en fonction de ce que le reste est dans la méthode, et parfois vous voulez vraiment pour accéder à la modification de la fermeture).

Plus d'infos:

http://blogs.msdn.com/abhinaba/archive/2005/10/18/482180.aspx

Encore plus d'infos:

http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx

http://blogs.msdn.com/oldnewthing/archive/2006/08/03/687529.aspx

http://blogs.msdn.com/oldnewthing/archive/2006/08/04/688527.aspx

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X