在C#中使用lambda表达式或匿名方法时,我们必须警惕对修改后的闭包陷阱的访问.例如:
foreach (var s in strings)
{
query = query.Where(i => i.Prop == s); // access to modified closure
...
}
Run Code Online (Sandbox Code Playgroud)
由于修改后的闭包,上面的代码将导致Where查询中的所有子句都基于最终值s.
正如这里所解释的那样,这是因为上面循环中s声明的变量foreach在编译器中被翻译成这样:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
Run Code Online (Sandbox Code Playgroud)
而不是像这样:
while (enumerator.MoveNext())
{
string s;
s = enumerator.Current;
...
}
Run Code Online (Sandbox Code Playgroud)
正如这里所指出的,在循环外声明变量没有性能优势,在正常情况下,我能想到这样做的唯一原因是你计划在循环范围之外使用变量:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
var finalString = s;
Run Code Online (Sandbox Code Playgroud)
但是,foreach循环中定义的变量不能在循环外使用: …
跟进:
如果我使用本地范围的变量运行一个函数,我的程序最终会抛弃该值 - 这让我完全糊涂了.
为什么会这样?
简单示例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, object> Dict = new Dictionary<string, object>() {
{ "1", new Dictionary<string, object>() {
{"Columns",new object[1]{ "name"} }
}},
{ "2", new Dictionary<string, object>() {
{"Columns",new object[1]{ "name"} }
}}
};
int i = 0;
foreach (KeyValuePair<string, object> record in Dict)
{
var _recordStored = record; //THIS IS(was) SUPPOSED TO …Run Code Online (Sandbox Code Playgroud)