Как я могу сделать этот специальный итератор 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);
}