在C#中使用lambda表达式或匿名方法时,我们必须小心访问修改的闭包陷阱。例如:
foreach (var s in strings)
{
query = query.Where(i => i.Prop == s); // access to modified closure
...
}
由于修改了闭包,上述代码将导致查询中的所有Where子句都基于s的最终值。
正如这里所解释的,这是因为上面foreach循环中声明的s变量在编译器中被这样翻译:
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循环是用内部作用域变量编译的,那么您是否可以用这种方式处理它们,或者这只是在匿名方法和lambda表达式可用或通用之前所做的任意选择,并且从那时起就没有修改过?