C# 访问修改后的闭包,这是一个重竖琴错误吗?

C# 访问修改后的闭包,这是一个重竖琴错误吗?,c#,lambda,resharper,closures,C#,Lambda,Resharper,Closures,我有最新的ReSharper 5.0版本1655,在这里我遇到了关于以下代码的“访问修改的闭包”的建议: var now = new DateTime(1970, 1, 1); var dates = new List<DateTime>(); dates.Where(d => d > now); ... now = new DateTime(); 这不应该通过立即执行查询来解决问题吗?不,这是resharper认为您在对集合进行循环时正在修改集合的内容,最有可能是日期

我有最新的ReSharper 5.0版本1655,在这里我遇到了关于以下代码的“访问修改的闭包”的建议:

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

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

不,这是resharper认为您在对集合进行循环时正在修改集合的内容,最有可能是日期。您可以放心地忽略此项。

不,这是resharper认为您在对集合进行循环时正在修改其内容,很可能是日期。你可以放心地忽略这个问题。

好的,现在你已经修改了这个问题,它完全有意义了。您正在修改闭包中使用的变量-这可能会产生意外的结果:

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.
}
事实上,这不仅仅是查询何时启动的问题——您可以在迭代结果时对其进行修改:

这将给出一个严格递增的日期序列。。。再一次,有点令人困惑


R对此提出警告是绝对正确的,IMO。它有时是有用的,但使用时要非常小心。

好的,现在你已经修改了这个问题,它完全有意义了。您正在修改闭包中使用的变量-这可能会产生意外的结果:

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.
}
事实上,这不仅仅是查询何时启动的问题——您可以在迭代结果时对其进行修改:

这将给出一个严格递增的日期序列。。。再一次,有点令人困惑


R对此提出警告是绝对正确的,IMO。它有时是有用的,但应小心使用。

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论坛上有一个链接,其中包括多个链接和进一步的解释。

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论坛上有一个链接,其中包括几个带有进一步解释的链接。

是否仅限于此代码?在那些台词之后,现在没有任务了?@Jon Skeet你说得对,在几行下面有一个任务!我会修改这个问题。就在那个代码上?在那些台词之后,现在没有任务了?@Jon Skeet你说得对,在几行下面有一个任务!我将修改这个问题。因为now是一个捕获的变量,所以在计算查询之前对其进行任何更改都很可能会产生与预期不同的结果,这正是R试图强调的。嗯,显然,问题被改为代码,他确实使用了一个循环,因为现在是一个捕获的变量。在计算查询之前对它的任何更改都很可能产生与预期不同的结果,这正是R试图强调的。嗯,显然问题被改为代码,他确实使用了一个循环。如果我调用ToList,这不应该立即执行查询,从而防止出现这种情况吗?@hmemcpy:警告仍然存在,因为R不知道闭包再也不用了。了解每一种可能使用闭包的方法是否意味着?R不知道ToList会立即执行查询,然后扔掉源代码。如果我调用ToList,这不应该立即执行查询,从而防止出现这种情况吗?@hmemcpy:警告仍然存在,因为R不知道闭包不再使用。了解每一种可能使用闭包的方法是否意味着?R不知道ToList会立即执行查询,然后丢弃源代码。