我怎么能做这个特殊的foreach迭代器?

时间:2010-12-08 21:43:05

标签: c# .net

  

可能重复:
  How to modify or delete items from an enumerable collection while iterating through it in C#

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

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

当我这样做时会发生这种情况:

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

我相信有一个特殊的迭代器可以很好地处理这个问题,就像Java一样。 那么,我怎么能在C#中做到这一点呢? 谢谢!

4 个答案:

答案 0 :(得分:5)

或者只是删除它而不需要手动迭代:

images.RemoveAll(image=>...)

适用于List<T>但许多其他容器不支持它。

处理IList<T>的O(n)解决方案:

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 :(得分:4)

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

答案 2 :(得分:2)

你不能用C#。

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

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

答案 3 :(得分: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);
}