Korzystając z wyrażeń lambda lub anonimowych metod w języku C #, musimy uważać na dostęp do zmodyfikowanej pułapki zamknięcia . Na przykład:
foreach (var s in strings)
{
query = query.Where(i => i.Prop == s); // access to modified closure
...
}
Ze względu na zmodyfikowane zamknięcie powyższy kod spowoduje, że wszystkie Where
klauzule w zapytaniu będą oparte na końcowej wartości s
.
Jak wyjaśniono tutaj , dzieje się tak, ponieważ s
zmienna zadeklarowana w foreach
powyższej pętli jest tłumaczona w kompilatorze w następujący sposób:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
zamiast tego:
while (enumerator.MoveNext())
{
string s;
s = enumerator.Current;
...
}
Jak wskazano tutaj , zadeklarowanie zmiennej poza pętlą nie ma żadnych korzyści w zakresie wydajności, aw normalnych okolicznościach jedynym powodem, dla którego mogę to zrobić, jest zaplanowanie użycia zmiennej poza zakresem pętli:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
var finalString = s;
Jednak zmiennych zdefiniowanych w foreach
pętli nie można używać poza pętlą:
foreach(string s in strings)
{
}
var finalString = s; // won't work: you're outside the scope.
Tak więc kompilator deklaruje zmienną w sposób, który czyni ją wysoce podatną na błąd, który często jest trudny do znalezienia i debugowania, a jednocześnie nie daje widocznych korzyści.
Czy istnieje coś, co można zrobić z foreach
pętlami w ten sposób, czego nie można było zrobić, gdyby były one skompilowane ze zmienną o zasięgu wewnętrznym, czy jest to tylko arbitralny wybór, który został dokonany, zanim anonimowe metody i wyrażenia lambda były dostępne lub powszechne, a które nie nie został zmieniony od tego czasu?
foreach
wyrażeniach lamda, które skutkują podobnym kodem, jak pokazano przez OP ...
String s; foreach (s in strings) { ... }
?