为什么我得到“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变量。