C#阻止Collection被修改exception

是否

foreach(T value in new List(oldList) ) 

当oldList包含1百万个对象T时危险(代价高昂)?

更常见的是,在枚举期间添加/删除元素时,枚举oldList的最佳方法是什么?

一般规则是,您不应修改您枚举的同一集合。 如果你想做类似的事情,请保留另一个集合,该集合将跟踪从原始集合中添加/删除的元素,然后在退出循环后,对原始集合执行添加/删除操作。

我通常只为要删除或添加的所有对象创建一个列表。

foreach我只是将项添加到相应的集合中,并在foreach完成后修改原始集合(循环遍历removeItemsaddItems集合)

像这样

 var itemsToBeRemoved = new List(); foreach (T item in myHugeList) { if (/**/) itemsToBeRemoved.Add(item); } myHugeList.RemoveRange(itemsToBeRemoved); 

如果你的意思是你可以从另一个线程添加/删除对象,我会:1 – 在添加/删除线程中同步线程2-,创建要添加或删除的项目列表3-然后在关键项中删除这些项目部分(所以它很小 – 在将项目添加到删除列表时不必同步)

如果你不想这样做,你可以使用for而不是foreach,这可以避免exception,但你必须格外小心,这样你就不会得到其他类型的例外

如果您使用Foreach循环来修改集合,那么您将收到如下错误。

 List li = new List(); li.Add("bhanu"); li.Add("test"); foreach (string s in li) { li.Remove(s); } 

解决方案 – 使用For Loop,如下所示。

 for (int i = 0; i < li.Count; i++) { li.RemoveAt(i); i--; } 

您可以在不使用枚举器的情况下遍历列表,所以请执行以下操作:

 for(int i = 0;i 

对我来说,第一件事是你应该考虑使用某种数据分页,因为拥有这样的1-milion-items-large list本身就很危险。

你听说过工作单元模式吗?

您可以实现它,以便标记对象以进行创建,更新或删除,之后,您可以调用“SaveChanges”,“Commit”或其他任何“应用更改”的工作,您就可以完成了。

例如,您遍历可枚举(oldList)并将它们标记为“delete”。 稍后,您调用“SaveChanges”,更抽象,通用的工作单元将遍历要处理的小的,已过滤的对象列表。

无论如何,避免列出百万件物品。 您应该使用分页的对象列表。

它会“慢”但除了在后台线程上运行之外,你无法做更多的事情。 例如,使用BackgroundWorker 。

如果列表上的操作仅发生在一个线程上,则正确的方法是添加要添加/删除的项目以分隔列表,并在迭代完成后执行这些操作。

如果你使用多个线程,你将不得不研究multithreading编程,例如使用锁或者更好的ReaderWriterLock 。

更新:正如另一个Stack Overflow问题中所提到的,现在可以在使用并发集合时在.NET 4.0 中轻松实现 。

foreach(新列表中的T值(oldList).ToList()) – 试一试

在枚举原始文件时,您可以使用标志将修改切换到临时列表。

///你在哪里枚举

 isBeingEnumerated = true foreach(T value in new List(oldList) ) isBeingEnumerated = false SyncList(oldList with temporaryList) 

///在枚举时修改的位置

 if isBeingEnumerated then use a temporaryList to make the changes.