我有最新的ReSharper 5.0版本(1655),我在下面的代码中遇到了“访问修改后的闭包”的建议:
var now = new DateTime(1970, 1, 1);
var dates = new List<DateTime>();
dates.Where(d => d > now);
...
now = new DateTime();
并且lambda表达式中的now
带有警告下划线。
我很确定这是一个ReSharper错误,但它真的是吗?
编辑:我应该检查得更好,代码后面有now
的作业。
编辑2 Jon Skeet的answer几乎可以解答这个问题,但以下内容如何:
var query = dates.Where(d => d > now).ToList();
这不应该通过立即执行查询来解决问题吗?
答案 0 :(得分:4)
是的,现在你已经修改了这个问题,这是完全合理的。您正在修改闭包中使用的变量 - 这会产生意外结果:
var now = new DateTime(1970, 1, 1);
var dates = new List<DateTime>();
var query = dates.Where(d => d > now);
...
now = new DateTime(1990, 1, 1);
foreach (DateTime date in query)
{
// This will only see dates after 1990, not after 1970
// This would confuse many developers.
}
事实上,这不仅仅是查询何时开始 - 您可以在迭代结果时修改 :
var now = new DateTime(1970, 1, 1);
var dates = new List<DateTime>();
var query = dates.Where(d => d > now);
...
foreach (DateTime date in query)
{
now = date;
Console.WriteLine(date);
}
这会给出严格增加的日期序列......再次,有些令人困惑。
对于这一点,R#是绝对正确的,IMO。它有时有用 - 但应谨慎使用。答案 1 :(得分:1)
ReSharper警告你的是now
的值是在lambda表达式中捕获的,而不是你认为执行lambda时的值。
要解决您的问题,您需要在使用之前将now
的值分配给局部变量:
var now = new DateTime(1970, 1, 1);
var dates = new List<DateTime>{new DateTime(2001, 12, 12)};
DateTime localNow = now;
dates.Where(d => d > localNow);
now = new DateTime(2003, 12, 12);
如果您想阅读更多内容,ReSharper论坛上会有一个post,其中包含几个链接以及进一步说明。
答案 2 :(得分:0)
这不是resharper,认为你正在修改集合的内容,而最有可能是dates
。你可以放心地忽略这一点。