При использовании лямбда-выражений или анонимных методов в C # мы должны опасаться доступа к измененной ловушке замыкания . Например:
foreach (var s in strings)
{
query = query.Where(i => i.Prop == s); // access to modified closure
...
}
Из-за измененного закрытия приведенный выше код приведет к тому, что все Where
предложения в запросе будут основаны на конечном значении s
.
Как объясняется здесь , это происходит потому, что s
переменная, объявленная в foreach
цикле выше, переводится следующим образом в компилятор:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
вместо этого:
while (enumerator.MoveNext())
{
string s;
s = enumerator.Current;
...
}
Как указывалось здесь , нет никаких преимуществ в производительности для объявления переменной вне цикла, и при нормальных обстоятельствах единственная причина, по которой я могу придумать для этого, - это если вы планируете использовать переменную вне области действия цикла:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
var finalString = s;
Однако переменные, определенные в foreach
цикле, не могут использоваться вне цикла:
foreach(string s in strings)
{
}
var finalString = s; // won't work: you're outside the scope.
Таким образом, компилятор объявляет переменную таким образом, что она очень подвержена ошибкам, которые часто трудно найти и отладить, но не дает ощутимых преимуществ.
Есть ли что-то, что вы можете сделать с foreach
циклами таким образом, что вы не смогли бы, если бы они были скомпилированы с переменной внутренней области видимости, или это просто произвольный выбор, который был сделан до того, как анонимные методы и лямбда-выражения были доступны или распространены, и который не было пересмотрено с тех пор?
foreach
лямда-выражениях, которые приводят к тому же коду, как показано ОП ...
String s; foreach (s in strings) { ... }
?