2011-12-01 51 views
1

我有这段代码的问题,当我做我的相交方法一切工作正常。List.Intersect结果改变后foreach

当我在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); 
} 

回答

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本身。

+0

你让我的一天!非常感谢! – Swell

1

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

因此,第二次调用Count枚举matchedRoles第二次枚举,导致第二次执行roles.Intersect(user.Roles)。由于您从用户中删除了该角色,因此它现在不会返回任何项目。

为了避免这种情况,从那里列举结果使用ToList一次,工作与枚举值:

var matchedRoles = roles.Intersect(user.Roles).ToList(); 
0

LINQ的使用延迟执行的:它本质上是做相交两次。一旦匹配的角色仍然在user.Roles中,并且一次在您的调用中删除该角色。

0

您的LINQ在您第二次访问它的时刻再次执行。如果你想得到一份参考文献的副本,你可以使用ToList方法并迭代它的项目