为什么我得到“collections被修改; 枚举操作可能不执行“不修改枚举的集合?

我有两个字符串集合:CollectionA是存储在系统中的对象的StringCollection属性,而CollectionB是在运行时生成的List。 如果存在任何差异,CollectionA需要更新以匹配CollectionB。 所以我设计了我期望的一个简单的LINQ方法来执行删除。

var strDifferences = CollectionA.Where(foo => !CollectionB.Contains(foo)); foreach (var strVar in strDifferences) { CollectionA.Remove(strVar); } 

但我得到一个"Collection was modified; enumeration operation may not execute"错误的strDifferences …即使它是一个单独的可枚举的被修改集合! 我最初明确地设计了这个来逃避这个错误,因为我的第一个实现会产生它(因为我在CollectionA进行枚举,只是删除了!CollectionB.Contains(str) )。 谁能解释为什么这个枚举失败?

这两者并非完全分开。 Where没有单独的集合副本。 它在内部保留对原始集合的引用,并在您请求时从中获取元素。

您可以通过添加ToList()来强制解决您的问题,以强制立即迭代集合。

 var strDifferences = CollectionA .Where(foo => !CollectionB.Contains(foo)) .ToList(); 

尝试稍微修改第一行:

 var strDifferences = CollectionA.Where(foo => !CollectionB.Contains(foo)).ToList(); 

我认为LINQ正在使用您的查询的延迟执行。 对ToList的调用将在枚举之前强制执行查询。

传回IEnumerable然后你在你的foreach (var strVar in strDifferences)中使用它foreach (var strVar in strDifferences)

然后,您尝试将其从创建IEnumerable的集合中删除。 您尚未创建新列表,它引用CollectionA来从中提取下一个项目,因此您无法编辑CollectionA

你也可以这样做:

 var strDifferences = CollectionA.Where (foo => CollectionB.Contains(foo)).ToList(); CollectionA = strDifferences; //or instead of reassigning CollectionA CollectionA.Clear(); CollectionA.AddRange(strDifferences); 

因为您要删除不在CollectionB中的那些。 只需查找那些,创建一个列表并将该列表分配给CollectionA变量。