Lorsque vous utilisez des expressions lambda ou des méthodes anonymes en C #, nous devons nous méfier de l' accès aux pièges de fermeture modifiés . Par exemple:
foreach (var s in strings)
{
query = query.Where(i => i.Prop == s); // access to modified closure
...
}
En raison de la fermeture modifiée, le code ci-dessus entraînera que toutes les Where
clauses de la requête seront basées sur la valeur finale de s
.
Comme expliqué ici , cela se produit car la s
variable déclarée dans la foreach
boucle ci-dessus est traduite comme ceci dans le compilateur:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
au lieu de comme ça:
while (enumerator.MoveNext())
{
string s;
s = enumerator.Current;
...
}
Comme indiqué ici , il n'y a aucun avantage en termes de performances à déclarer une variable en dehors de la boucle, et dans des circonstances normales, la seule raison pour laquelle je peux penser à cela est si vous prévoyez d'utiliser la variable en dehors de la portée de la boucle:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
var finalString = s;
Cependant les variables définies dans une foreach
boucle ne peuvent pas être utilisées en dehors de la boucle:
foreach(string s in strings)
{
}
var finalString = s; // won't work: you're outside the scope.
Ainsi, le compilateur déclare la variable d'une manière qui la rend très sujette à une erreur qui est souvent difficile à trouver et à déboguer, tout en ne produisant aucun avantage perceptible.
Y a-t-il quelque chose que vous pouvez faire avec des foreach
boucles de cette façon que vous ne pourriez pas faire si elles étaient compilées avec une variable de portée interne, ou est-ce juste un choix arbitraire qui a été fait avant que les méthodes anonymes et les expressions lambda ne soient disponibles ou communes, et qui n'ont pas pas été révisé depuis?
foreach
mais d'expressions lamda résultant en un code similaire à celui de l'OP ...
String s; foreach (s in strings) { ... }
?