2010-12-08 55 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); 
}