Результаты List.Intersect меняются после foreach - PullRequest
1 голос
/ 01 декабря 2011

У меня проблема с этим фрагментом кода, когда я выполняю свой метод пересечения, все работает нормально.

Когда я делаю подсчет на моем пересечении до того, как у меня есть 1.

После foreach, если счет снова после foreach, у меня есть 0, почему это происходит?Всегда должно быть 1 ...

var matchedRoles = roles.Intersect(user.Roles);
int before = matchedRoles.Count();

foreach (var matchedRole in matchedRoles)
{
    user.Roles.Remove(matchedRole);
}

int after = matchedRoles.Count();
if (matchedRoles.Any())
{
    accountRepository.Update(user);   
}

Ответы [ 4 ]

1 голос
/ 01 декабря 2011

Intersect использует отложенное выполнение.Это означает, что каждый раз, когда вы перечисляете результат, код выполняется.

Итак, ваш второй вызов Count перечисляет перечисляемое matchedRoles во второй раз, вызывая второе выполнение roles.Intersect(user.Roles).Поскольку вы удалили роль у пользователя, теперь она не возвращает элементов.

Чтобы избежать этого, перечислите результат один раз, используя ToList, и поработайте с перечисленными значениями:

var matchedRoles = roles.Intersect(user.Roles).ToList();
1 голос
/ 01 декабря 2011

Это происходит потому, что запросы LINQ оцениваются лениво: результат не создается до тех пор, пока он не должен быть (что происходит всякий раз, когда вы вызываете Count). Само собой разумеется, что если вы измените user.Roles между тем, Count, вычисленное после модификации, будет другим.

Если вы хотите «исправить» результат, то вы должны заставить LINQ сделать локальную копию результатов, например, как это:

// Here, ToArray() forces LINQ to immediately produce the results
var matchedRoles = roles.Intersect(user.Roles).ToArray();

Таким образом, любые дальнейшие операции с matchedRoles будут работать с фиксированным «снимком» и будут давать те же результаты, если вы не измените сам matchedRoles.

0 голосов
/ 01 декабря 2011

ваш LINQ будет снова выполнен в тот момент, когда вы обращаетесь к нему во второй раз.Если вы хотите получить копию ссылок, вы можете использовать метод ToList и перебирать его элементы

0 голосов
/ 01 декабря 2011

Linq использует отложенное выполнение: по сути, он дважды пересекается.Один раз с соответствующей ролью все еще в user.Roles, и один раз после вашего вызова, чтобы удалить роль.

...