开发者

Access to modified closure, is this a ReSharper bug?

I have the latest ReSharper 5.0 build (1655), where I have encountered the suggestion 'Access to modified closure' on the following code:

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

and 开发者_如何学运维the now inside the lambda expression is underlined with the warning.

I'm pretty sure that's a ReSharper bug, but is it really?

EDIT: I should have checked better, there was an assignment to now later in the code.

EDIT 2 Jon Skeet's answer below pretty much answers this, but what about the following:

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

Shouldn't this solve the problem by executing the query immediately?


Right, now you've modified the question, it makes complete sense. You're modifying a variable used within a closure - which can produce unexpected results:

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.
}

In fact, it's not just a matter of when the query starts - you could modify it while iterating over the results:

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);
}

That will give a strictly-increasing sequence of dates... again, somewhat confusing.

R# is absolutely right to warn about this, IMO. It can sometimes be useful - but should be used with great care.


What ReSharper is warning you about is that the value of now is being captured in the lambda expression and is not the value you think it is when the lambda gets executed.

To solve your problem, you need to assign the value of now to a local variable before you use it:

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);

If you want to read more, the ReSharper forum has a post on it which includes several links with further explanation.


No this is resharper thinking you are modifying the contents of a collection while looping over it, dates most probably. You can safely ignore this.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜