2010-12-08 52 views
0

Possible Duplicate:
How to modify or delete items from an enumerable collection while iterating through it in C#我该如何做这个特殊的foreach迭代器?

听,我不想知道基本的foreach。我谈论的是一个控制着这一错误:

 
"The enumerator is not valid because the collection changed." 

我这样做时出现:

foreach(Image image in images) 
{ 
    if(...) 
    { 
     images.remove(image) 
    } 
} 

我相信这是处理这个问题很好,因为Java有一个特殊的迭代。那么,我该如何在C#中执行此操作? 谢谢!

回答

4
for (var i = 0; i < images.Count; ++i) 
{ 
    if (...) 
    { 
     images.RemoveAt(i); 
     --i; 
    } 
} 
+0

但如果我这样做,我相信我会失去下一个对象,考虑到我使用的画布。例如:图像,我删除索引2的对象。所以索引2的对象将移动到索引2作为列表。因此,当我尝试获取下一个索引值3时,索引3的旧对象将位于索引2处。因此,我将失去他。 – Seva 2010-12-08 21:47:11

+0

@Alan,这就是`--i;`这一行的用途。这会调整索引,以避免遗漏任何项目。 – 2010-12-08 21:50:10

+0

这就是`--i`纠正的问题。去除时递减的技术很有趣。我通常写我的循环,有时倒退和双测试。 – CodesInChaos 2010-12-08 21:52:03

2

你不能在C#中做到这一点。

你可以做的是收集您想要删除的对象,然后将其删除:

Image[] imagesToRemove = images.Where(image => ...).ToArray(); 
foreach (Image image in imagesToRemove) 
    images.remove(image); 
5

或者只是将其删除,而无需手动迭代都:

images.RemoveAll(image=>...) 

文选List<T>但许多其他容器不支持它。

为O(n)解决方案上IList<T>工作:

void RemoveWhere(this IList<T> list,Predicate<T> pred) 
{ 
    int targetIndex=0; 
    for(int srcIndex=0;srcIndex<list.Count;srcIndex++) 
    { 
     if(pred(list[srcIndex])) 
     { 
     list[targetIndex]=list[srcIndex]; 
     targetIndex++; 
     } 
     for(int i=list.Count-1;i>=targetIndex;i--) 
     list.RemoveAt(i); 
    } 
} 

可以通过不分配,直到你遇到第一个删除的项目会加快一点。

1

肯特的答案将工作给予实施IList<T>。对于那些你不需要建立你想要移除的东西的列表。例如:

public static void RemoveWhere<T>(this ICollection<T> self, Func<T, bool> predicate) 
{ 
    var toRemove = self.Where(predicate).ToList(); 

    foreach (var i in toRemove) 
     self.Remove(i); 
}