foreach(T value in new List<T>(oldList))
是危险的(昂贵的)时oldList包含1个百万物品T的?
更多generaly什么是枚举oldList因为元素可以添加/枚举过程中移除...
foreach(T value in new List<T>(oldList))
是危险的(昂贵的)时oldList包含1个百万物品T的?
更多generaly什么是枚举oldList因为元素可以添加/枚举过程中移除...
我通常只是创建一个列表被删除或添加的所有对象的最佳途径。
内foreach
我只是添加的项目,以适当的集合和修改原始集合后foreach
已经完成(通过removeItems
和addItems
收集循环)
一般的规则是,你不应该修改同您正在枚举的集合。如果你想做这样的事情,保留另一个集合,它将跟踪哪些元素添加/从原始集合中删除,然后在退出循环后,对原始集合执行添加/删除操作。
好吧,但实际上它是另一个可以修改集合的线程。出于某种原因,我无法同步迭代与添加/删除。 – Toto 2011-02-15 10:34:27
正如我更新的答案中所述,如果您使用的是.NET 4.0,请考虑使用“并发集合”。 – 2011-02-15 11:46:04
这将是'缓慢',但除了在后台线程上运行它外,您可以做的更多。例如。使用BackgroundWorker。
如果您的列表操作仅发生在一个线程上,则正确的方法是将项目添加/删除到单独列表中,并在迭代完成后执行这些操作。
如果你使用多线程,你将不得不考虑多线程编程,使用locks或可能更好一个ReaderWriterLock。
UPDATE: 作为另一个Stack Overflow question提到的,这是目前可能没有在.NET 4.0中when using concurrent collections任何努力。
你可以遍历列表,而不使用枚举,所以这样做......
for(int i = 0;i<oldList.Count;i++) {
var value = oldList[i];
...
if(itemRemoveCondition) {
oldList.RemoveAt(i--);
}
}
我发现那种混乱;为什么不简单地在列表中向后循环?那么你不需要混合递增和递减索引。 – 2011-02-15 10:31:48
如果你的意思是你可以添加/从另一个线程删除对象,我想: 1同步线程 2-在添加/删除线程中,创建要添加或删除的项目列表 3-然后在关键部分中删除这些项目(因此它很小 - 在添加项目时不必同步到删除列表)
如果你不想这样做,你可以用它来代替fo达成,这将避免该异常,但你必须采取额外的照顾,让你没有得到其他类型的异常
就这样
var itemsToBeRemoved = new List<T>();
foreach (T item in myHugeList)
{
if(/*<condition>*/)
itemsToBeRemoved.Add(item);
}
myHugeList.RemoveRange(itemsToBeRemoved);
对我来说的,第一件事情是你应该考虑使用一些这种类型的数据分页,因为拥有这样的1千万条目大的列表本身可能是危险的。
您是否听说过工作单元模式?
您可以实现它,以便标记创建,更新或删除对象,然后调用“SaveChanges”,“Commit”或任何其他执行“应用更改”的工作,您就完成了。
例如,您遍历枚举(oldList)并将它们标记为“delete”。之后,您调用“SaveChanges”,更抽象的通用工作单元将迭代小型,经过筛选的对象列表以供处理。
反正避免的畅想项的列表。您应该使用分页的对象列表。
尝试用于词典。
int [] temp = Dictionary.Keys.ToArray();
foreach (var c in temp)
{
if (condition)
{
//Your codes
}
else
{
Dictionary.Remove(c);
//OR
Dictionary.Add(c);
}
的foreach(在新列表T中值(oldList).ToList()) - 给一个尝试
如果您使用的foreach循环修改集合,那么你会得到这个错误如下。
List<string> li = new List<string>();
li.Add("bhanu");
li.Add("test");
foreach (string s in li)
{
li.Remove(s);
}
解决方法 - 使用For循环如下。
for (int i = 0; i < li.Count; i++)
{
li.RemoveAt(i);
i--;
}
您可以使用标志将修改切换到临时列表,而原始枚举。
///你在哪里枚举
isBeingEnumerated = true
foreach(T value in new List<T>(oldList))
isBeingEnumerated = false
SyncList(oldList with temporaryList)
///你在哪里,而枚举
if isBeingEnumerated then
use a temporaryList to make the changes.
好像有两个不同的问题在这里修改。我不确定他们为什么合并。 – 2011-02-15 10:29:26