2010-04-07 34 views
1

我有最新的ReSharper的5.0版本(1655),在那里我遇到的建议“以修改封访问”在下面的代码:访问修改的闭包,这是一个ReSharper错误?

var now = new DateTime(1970, 1, 1); 
var dates = new List<DateTime>(); 
dates.Where(d => d > now); 
... 
now = new DateTime(); 

now lambda表达式内部强调与警告。

我很确定这是一个ReSharper错误,但它是真的吗?

编辑:我应该更好地检查,在代码后面有一个now的任务。

EDIT 2乔恩斯基特下面几乎回答了这个,但对于下面的answer

var query = dates.Where(d => d > now).ToList(); 

不应该通过这种立即执行查询解决问题吗?

+2

字面上只是在该代码?在这些行之后没有分配到“现在”? – 2010-04-07 10:44:25

+0

@Jon Skeet你是对的,有一个任务几行下来!我会修改这个问题。 – 2010-04-07 10:48:00

回答

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#绝对正确地警告这个,国际海事组织。它可以有时是有用的 - 但应该非常小心使用。

+0

如果我调用'ToList()',应该不会立即执行查询,从而防止这种情况? – 2010-04-07 10:55:33

+0

@hmemcpy:是的,没错。 – 2010-04-07 11:05:16

+0

但是警告仍然存在,所以也许这可能是一个ReSharper错误... – 2010-04-07 11:09:48

0

不,这是resharper认为你正在修改集合的内容,而循环它,最有可能的是dates。你可以放心地忽略这一点。

+0

由于'now'是一个捕获的变量,因此在对查询进行评估之前对其进行的任何更改都很可能会产生与预期不同的结果,这是R#试图突出显示的结果。 – 2010-04-07 10:52:01

+0

-1:他不能安全地忽略它 – ANeves 2010-04-07 11:14:58

+0

嗯显然问题被改变为代码他使用循环的代码 – 2010-04-07 11:29:58

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,其中包括几个链接进一步解释。

相关问题