Как я могу сделать этот специальный итератор foreach?

Возможный дубликат:
Как изменить или удалить элементы из перечислимой коллекции, итерации через нее в С#

Слушайте, я не хочу знать о базовом foreach. Я говорю об этом, который управляет этой ошибкой:

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

Что происходит, когда я это делаю:

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

Я считаю, что есть специальный итератор, который отлично справляется с этим, как это имеет Java. Итак, как я могу это сделать на С#, пожалуйста? Спасибо!

Ответ 1

Или просто удалите его без ручного итерации вообще:

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);
    }
}

Можно немного ускорить, не назначая, пока вы не ударите первый удаленный элемент.

Ответ 2

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

Ответ 3

Вы не можете сделать это на С#.

Что вы можете сделать, это собрать объекты, которые хотите удалить, и удалить их:

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

Ответ 4

Ответ Kent будет работать с учетом того, что реализует 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);
}