ReSharper中修改了闭包警告

Sar*_*els 4 .net c# resharper closures

我希望有人可以向我解释在这段代码中会发生什么坏事,这会导致ReSharper给出"访问修改后的封闭"警告:

bool result = true;

foreach (string key in keys.TakeWhile(key => result))
{
    result = result && ContainsKey(key);
}

return result;
Run Code Online (Sandbox Code Playgroud)

即使上面的代码看起来很安全,在其他"修改后的闭包"实例中会发生什么坏事?我经常在使用LINQ查询时看到这个警告,我倾向于忽略它,因为我不知道会出现什么问题.ReSharper尝试通过创建对我来说毫无意义的第二个变量来解决问题,例如它将foreach上面的行更改为:

bool result1 = result;
foreach (string key in keys.TakeWhile(key => result1))
Run Code Online (Sandbox Code Playgroud)

更新:在附注中,显然整个代码块可以转换为以下语句,这不会导致修改后的闭包警告:

return keys.Aggregate(
    true,
    (current, key) => current && ContainsKey(key)
);
Run Code Online (Sandbox Code Playgroud)

Dav*_*wns 8

在那个特定的代码中没有,请以下面的例子为例:

int myVal = 2;

var results = myDatabase.Table.Where(record => record.Value == myVal);

myVal = 3;

foreach( var myResult in results )
{
    // TODO: stuff
}
Run Code Online (Sandbox Code Playgroud)

看起来result会返回Value所有的记录,2因为这是myVal在声明查询时设置的内容.但是,由于延迟执行,它实际上将是Value的所有记录,3因为在迭代之前不会执行查询.

在您的示例中,该值未被修改,但Resharper警告您它可能是并且延迟执行可能会导致您出现问题.


SLa*_*aks 6

修改result变量时,闭包(在lambda表达式中使用变量)将获取更改.

对于那些不完全理解闭包的程序员来说,这经常是意外的惊喜,所以Resharper会对此发出警告.

通过创建result1仅在lambda表达式中使用的单独变量,它将忽略对原始result变量的任何后续更改.

在你的代码中,你依靠闭包来获取对原始变量的更改,以便它知道何时停止.

顺便说一句,没有LINQ编写函数的最简单方法是这样的:

foreach (string key in keys) {
    if (ContainsKey(key))
        return true;   
}
return false;
Run Code Online (Sandbox Code Playgroud)

使用LINQ,您只需调用Any():

return keys.Any<string>(ContainsKey);
Run Code Online (Sandbox Code Playgroud)