Ao usar expressões lambda ou métodos anônimos em C #, precisamos ter cuidado com o acesso à armadilha de fechamento modificada . Por exemplo:
foreach (var s in strings)
{
query = query.Where(i => i.Prop == s); // access to modified closure
...
}
Devido ao fechamento modificado, o código acima fará com que todas as Where
cláusulas da consulta sejam baseadas no valor final des
.
Como explicado aqui , isso acontece porque a s
variável declarada no foreach
loop acima é traduzida assim no compilador:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
em vez de assim:
while (enumerator.MoveNext())
{
string s;
s = enumerator.Current;
...
}
Conforme indicado aqui , não há vantagens de desempenho em declarar uma variável fora do loop e, em circunstâncias normais, a única razão pela qual posso pensar nisso é se você planeja usar a variável fora do escopo do loop:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
var finalString = s;
No entanto, variáveis definidas em um foreach
loop não podem ser usadas fora do loop:
foreach(string s in strings)
{
}
var finalString = s; // won't work: you're outside the scope.
Portanto, o compilador declara a variável de uma maneira que a torna altamente propensa a um erro que geralmente é difícil de encontrar e depurar, sem produzir benefícios perceptíveis.
Existe algo que você pode fazer com foreach
loops dessa maneira que não seria possível se eles fossem compilados com uma variável com escopo interno ou essa é apenas uma escolha arbitrária que foi feita antes que métodos anônimos e expressões lambda estivessem disponíveis ou comuns e que não foi revisado desde então?
foreach
, mas sobre expressões Lamda, resultando em código semelhante como mostrado pelo OP ...
String s; foreach (s in strings) { ... }
?