37 votes

L'utilisation des variables par foreach a-t-elle été modifiée dans C# 5 ?

Dans cette réponse https://stackoverflow.com/a/8649429/1497 Eric Lippert déclare : "Pour votre information, il est fort probable que nous corrigions ce problème dans la prochaine version de C# ; c'est un point sensible pour les développeurs" en ce qui concerne la façon dont les boucles foreach utilisent la variable.

Dans la prochaine version, chaque fois que vous exécutez la boucle "foreach", nous générerons une nouvelle variable de boucle plutôt que de refermer la même variable à chaque fois. Il s'agit d'un changement "cassant" mais dans la grande majorité des cas, la "cassure" sera réparée plutôt que de causer des bugs.

Je n'ai pas été en mesure de trouver quoi que ce soit indiquant que ce changement a déjà été effectué. Y a-t-il une indication que la boucle foreach fonctionnera de cette manière en C# 5 ?

55voto

Jeff Yates Points 36725

Il s'agit d'une modification du langage C#, et non du cadre .NET. Par conséquent, elle n'affecte que le code compilé sous C# 5.0, quelle que soit la version du framework .NET sur lequel ce code sera exécuté.

C# 5.0

La section 8.8.4 de la spécification indique clairement que ce changement a été effectué. Plus précisément, la page 249 de la spécification C# 5.0 indique que :

foreach (V v in x) embedded-statement

est alors étendu à :

{
    E e = ((C)(x)).GetEnumerator();
    try {
        while (e.MoveNext()) {
            V v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally {
        … // Dispose e
    }
}

Et plus tard :

Le placement de v à l'intérieur de la boucle while est important pour la façon dont il est capturée par toute fonction anonyme apparaissant dans la déclaration intégrée.

C# 4.0

Cette modification de la spécification est évidente si l'on compare avec la spécification C# 4.0 qui indique (à nouveau, dans la section 8.8.4, mais cette fois, page 247) :

foreach (V v in x) embedded-statement

est alors étendu à :

{
    E e = ((C)(x)).GetEnumerator();
    try {
        V v;
        while (e.MoveNext()) {
            v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally {
        … // Dispose e
    }
}

Notez que la variable v est déclaré à l'extérieur de la boucle et non à l'intérieur, comme c'est le cas en C# 5.0.

Nota

Vous pouvez trouver la spécification C# dans le dossier d'installation de Visual Studio sous VC#\Specifications\1033 . C'est le cas pour VS2005, VS2008, VS2010 et VS2012, vous donnant accès aux spécifications pour C# 1.2, 2.0, 3.0, 4.0 et 5.0. Vous pouvez également trouver les spécifications sur MSDN en recherchant C# Specification .

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