Під час використання лямбда-виразів або анонімних методів у 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) { ... }
?