Неожиданно переоценка лямбда-оценок? - PullRequest
0 голосов
/ 05 мая 2020

Должно быть что-то, чего я не понимаю в вычислениях лямбда и установке встроенных свойств лямбда. У меня есть следующий код:

var zeroGroupings = ruleList.Rules.Where(r => r.DiagnosticGrouping == 0); // line 1
var oneGroupings = ruleList.Rules.Where(r => r.DiagnosticGrouping == 1); // line 2
var twoGroupings = ruleList.Rules.Where(r => r.DiagnosticGrouping == 2); // line 3

zeroGroupings.ForEach(r => r.DiagnosticGrouping = 1); // line 4
oneGroupings.ForEach(r => r.DiagnosticGrouping = 2); // line 5
twoGroupings.ForEach(r => r.DiagnosticGrouping = 3); // line 6

ПРИМЕЧАНИЯ: ruleList.Rules - это коллекция (IEnumerable) объектов Rule. Сохраняя его простым и минимальным, я не думаю, что кому-то нужно много знать ни о ruleList, ни о ruleList.Rules, кроме объекта Rule, у которого есть свойство с именем DiagnosticGrouping.

Возьмем этот сценарий :

Предположим, что ruleList.Rules содержит 2 объекта Rule, и оба имеют значение DiagnosticGrouping 0. Строки 1-4 выполняются, как ожидалось.

zeroGroupings has a count of 2. 
oneGroupings has a count of 0.
twoGroupings has a count of 0.

Все, как ожидалось.

После выполнения строки 4 оба моих объекта 2 Rule имеют DiagnosticGrouping 1, как и ожидалось. Однако после выполнения строки 5 у объектов 2 Rule внезапно появляется DiagnosticGrouping 2. WTH? После выполнения строки 6 оба объекта правил теперь имеют DiagnosticGrouping равное 3.

Я надеялся, что в этом сценарии строки 5 и 6 не будут соответствовать чему-либо и, таким образом, ничего не будут делать. Кажется, что строки 2 и 3 каким-то образом переоцениваются в строках 5 и 6 и, таким образом, совпадают, и, таким образом, свойство снова устанавливается. Я этого не понимаю.

Что мне нужно сделать, чтобы все работало должным образом?

1 Ответ

2 голосов
/ 05 мая 2020

Where - запрос отложенного выполнения. Он не выполняет немедленную оценку и не заполняет коллекцию; скорее, он выполнил , когда он сам был повторен - сканирование исходного источника на совпадения. Это происходит каждый раз при повторении. Для этого есть причины, включая возможность компоновки и использование памяти. Фактически, не только исходные данные могут изменяться между созданием запроса и итерацией, но и из-за того, как работают «захваченные переменные», сам фильтр может измениться в это время!

В основном: если вы хотите, чтобы он выполнялся сейчас в список добавьте .ToList() после Where(...):

var zeroGroupings = ruleList.Rules.Where(r => r.DiagnosticGrouping == 0).ToList();
...