foreach(T value in new List<T>(oldList) )
当oldList包含1百万个对象T时,是危险的(代价高昂)?
更常见的是,在枚举期间添加/删除元素时,枚举oldList的最佳方法是什么...
答案 0 :(得分:8)
一般规则是,您不应修改您枚举的同一集合。如果你想做类似的事情,请保留另一个集合,该集合将跟踪从原始集合中添加/删除的元素,然后在退出循环后,对原始集合执行添加/删除操作。
答案 1 :(得分:4)
我通常只为要删除或添加的所有对象创建一个列表。
在foreach
中,我只是将项目添加到相应的集合中,并在foreach
完成后修改原始集合(循环遍历removeItems
和addItems
集合)
答案 2 :(得分:4)
就像这样
var itemsToBeRemoved = new List<T>();
foreach (T item in myHugeList)
{
if (/*<condition>*/)
itemsToBeRemoved.Add(item);
}
myHugeList.RemoveRange(itemsToBeRemoved);
答案 3 :(得分:1)
如果你的意思是你可以从另一个线程添加/删除对象,我会: 1 - 同步线程 2-在添加/删除线程中,创建要添加或删除的项目列表 3-然后在关键部分删除这些项目(因此它很小 - 在将项目添加到删除列表时不必同步)
如果您不想这样做,您可以使用for而不是foreach,这样可以避免异常,但您必须格外小心,以免出现其他类型的异常
答案 4 :(得分:1)
如果您使用Foreach循环来修改集合,那么您将收到如下错误。
List<string> li = new List<string>();
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--;
}
答案 5 :(得分:0)
它会“慢”但除了在后台线程上运行之外,你无法做更多的事情。例如。使用BackgroundWorker。
如果列表上的操作仅发生在一个线程上,则正确的方法是添加要添加/删除的项目以分隔列表,并在迭代完成后执行这些操作。
如果使用多个线程,则必须研究多线程编程,例如:使用locks或更好的ReaderWriterLock。
更新: 正如另一个Stack Overflow question中所提到的,现在可以在.NET 4.0 when using concurrent collections中毫不费力地实现。
答案 6 :(得分:0)
您可以在不使用枚举器的情况下遍历列表,所以请执行类似......
的操作for(int i = 0;i<oldList.Count;i++) {
var value = oldList[i];
...
if(itemRemoveCondition) {
oldList.RemoveAt(i--);
}
}
答案 7 :(得分:0)
对我而言,首先应该考虑使用某种数据分页,因为拥有这样的1百万项大型列表本身就很危险。
您是否听说过工作单元模式?
您可以实现它,以便标记对象以进行创建,更新或删除,之后,您可以调用“SaveChanges”,“Commit”或其他任何“应用更改”的工作,您将完成。< / p>
例如,您遍历可枚举(oldList)并将其标记为“delete”。稍后,您调用“SaveChanges”,更抽象,通用的工作单元将遍历要处理的小的,已过滤的对象列表。
无论如何,请避免使用百万件物品。您应该使用分页的对象列表。
答案 8 :(得分:0)
foreach(新列表中的T值(oldList).ToList()) - 试一试
答案 9 :(得分:0)
您可以使用标志将修改切换到临时列表,同时枚举原始文件。
///您要枚举的地方
lintOptions {
disable 'MissingTranslation'
}
///在枚举时修改的位置
isBeingEnumerated = true
foreach(T value in new List<T>(oldList) )
isBeingEnumerated = false
SyncList(oldList with temporaryList)