Доступ к измененному закрытию, это ошибка ReSharper? - PullRequest
1 голос
/ 07 апреля 2010

У меня последняя сборка ReSharper 5.0 (1655), где я обнаружил предложение «Доступ к измененному замыканию» в следующем коде:

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

и now внутри лямбда-выражения:подчеркнуто предупреждением.

Я почти уверен, что это ошибка ReSharper, но так ли это на самом деле?

РЕДАКТИРОВАТЬ: Я должен был проверить лучше, было заданиеnow позже в коде.

РЕДАКТИРОВАТЬ 2 Ответ Джона Скита ниже в значительной степени отвечает на этот вопрос, но как насчет следующего:

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

Разве это не решит проблему путем немедленного выполнения запроса?

Ответы [ 3 ]

4 голосов
/ 07 апреля 2010

Правильно, теперь вы изменили вопрос, это имеет смысл. Вы изменяете переменную, используемую в замыкании, что может привести к неожиданным результатам:

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 # абсолютно правильно предупредить об этом, ИМО. иногда может быть полезным, но его следует использовать с большой осторожностью.

1 голос
/ 07 апреля 2010

ReSharper предупреждает вас о том, что значение now фиксируется в лямбда-выражении, а не то значение, которое вы думаете, когда оно исполняется.

Чтобы решить вашу проблему, вам нужно присвоить значение 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 есть сообщение , содержащее несколько ссылок с дополнительными пояснениями.

0 голосов
/ 07 апреля 2010

Нет, это более резкое представление о том, что вы изменяете содержимое коллекции, зацикливаясь на ней, dates наиболее вероятно. Вы можете смело игнорировать это.

...