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)
在那个特定的代码中没有,请以下面的例子为例:
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警告您它可能是并且延迟执行可能会导致您出现问题.
修改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)
归档时间: |
|
查看次数: |
2264 次 |
最近记录: |