1

我对这段代码有疑问,当我执行 intersect 方法时,一切正常。

当我在 foreach 之前对我的交叉点进行计数时,我有 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

4 回答 4

1

发生这种情况是因为 LINQ 查询是惰性求值的:直到需要时才会产生结果(即每当您调用 时Count)。按理说,如果user.Roles同时修改,修改Count后的计算结果会有所不同。

如果要“修复”结果,则必须强制 LINQ 制作结果的本地副本,例如:

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

这样,matchedRoles只要您不修改matchedRoles自身,任何进一步的操作都将在固定的“快照”上工作并产生相同的结果。

于 2011-12-01T15:56:24.547 回答
1

Intersect使用延迟执行。这意味着,每次枚举结果时,都会执行代码。

因此,您第二次调用CountenumerablematchedRoles第二次,导致第二次执行roles.Intersect(user.Roles). 因为您从用户中删除了角色,所以它现在不返回任何项目。

为避免这种情况,请在使用时枚举结果ToList并从那里使用枚举值:

var matchedRoles = roles.Intersect(user.Roles).ToList();
于 2011-12-01T15:56:39.960 回答
0

Linq 使用延迟执行:它本质上执行了两次相交。一次,匹配的角色仍在 user.Roles 中,一次在您调用删除角色后。

于 2011-12-01T15:56:52.360 回答
0

当您第二次访问它时,您的 LINQ 会再次执行。如果您想获取引用的副本,您可以使用 ToList 方法并迭代其项目

于 2011-12-01T15:57:29.357 回答