Коллекция была изменена; операция перечисления не может выполняться в ArrayList [дубликат]
этот вопрос уже есть ответ здесь:
Я пытаюсь удалить элемент из ArrayList и я получаю это исключение:Collection was modified; enumeration operation may not execute.
какие идеи?
9 ответов:
вы удаляете элемент во время
foreach, да? Просто, вы не можете. Существует несколько распространенных вариантов здесь:
- использовать
List<T>иRemoveAllСвыполнить итерации в обратном направлении по индексу, удаление соответствующие элементы
for(int i = list.Count - 1; i >= 0; i--) { if({some test}) list.RemoveAt(i); }использовать
foreach, и поместите соответствующие элементы во второй список; теперь перечислите второй список и удалите эти элементы из первого (если вы видите, что я имею в виду)
вот пример (извините за возможные описки)
var itemsToRemove = new ArrayList(); // should use generic List if you can foreach (var item in originalArrayList) { if (...) { itemsToRemove.Add(item); } } foreach (var item in itemsToRemove) { originalArrayList.Remove(item); }или если вы используете 3.5, Linq делает Первый БИТ проще:
itemsToRemove = originalArrayList .Where(item => ...) .ToArray(); foreach (var item in itemsToRemove) { originalArrayList.Remove(item); }заменить "..."с вашим условием, которое определяет, должен ли элемент быть удален.
один из способов-добавить удаляемые элементы в новый список. Затем перейдите и удалите эти элементы.
мне нравится повторять назад с помощью
forпетли, но это может стать утомительным по сравнению сforeach. Одно из решений, которое мне нравится, - это создать перечислитель, который пересекает список назад. Вы можете реализовать это как метод расширения наArrayListилиList<T>. Реализация дляArrayListниже.public static IEnumerable GetRemoveSafeEnumerator(this ArrayList list) { for (int i = list.Count - 1; i >= 0; i--) { // Reset the value of i if it is invalid. // This occurs when more than one item // is removed from the list during the enumeration. if (i >= list.Count) { if (list.Count == 0) yield break; i = list.Count - 1; } yield return list[i]; } }реализация
List<T>аналогично.public static IEnumerable<T> GetRemoveSafeEnumerator<T>(this List<T> list) { for (int i = list.Count - 1; i >= 0; i--) { // Reset the value of i if it is invalid. // This occurs when more than one item // is removed from the list during the enumeration. if (i >= list.Count) { if (list.Count == 0) yield break; i = list.Count - 1; } yield return list[i]; } }в приведенном ниже примере перечислитель используется для удаления всех четных целых чисел из
ArrayList.ArrayList list = new ArrayList() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; foreach (int item in list.GetRemoveSafeEnumerator()) { if (item % 2 == 0) list.Remove(item); }
не изменяйте список внутри цикла, который повторяется через список.
используйтеfor()илиwhile()с индексом, идя назад по списку. (Это позволит вам удалить вещи без получения недопустимого индекса.)var foo = new List<Bar>(); for(int i = foo.Count-1; i >= 0; --i) { var item = foo[i]; // do something with item }
Я что-то пропустила? Кто-нибудь поправьте меня, если я ошибаюсь.
list.RemoveAll(s => s.Name == "Fred");
Я согласен с несколькими пунктами, которые я прочитал в этом посте, и я включил их в свое решение, чтобы решить ту же проблему, что и исходная публикация.
тем не менее, комментарии, которые я оценил:
" Если вы не используете .NET 1.0 или 1.1, используйте
List<T>вместоArrayList. "" кроме того, добавить пункт(ы) для удаления в новый список. Затем перейдите и удалите эти элементы." .. в моем случае я просто создал новую Список и заполненный им с допустимыми значениями данных.
например
private List<string> managedLocationIDList = new List<string>(); string managedLocationIDs = ";1321;1235;;" // user input, should be semicolon seperated list of values managedLocationIDList.AddRange(managedLocationIDs.Split(new char[] { ';' })); List<string> checkLocationIDs = new List<string>(); // Remove any duplicate ID's and cleanup the string holding the list if ID's Functions helper = new Functions(); checkLocationIDs = helper.ParseList(managedLocationIDList); ... public List<string> ParseList(List<string> checkList) { List<string> verifiedList = new List<string>(); foreach (string listItem in checkList) if (!verifiedList.Contains(listItem.Trim()) && listItem != string.Empty) verifiedList.Add(listItem.Trim()); verifiedList.Sort(); return verifiedList; }
используя
ArrayListтакже вы можете попробовать такойArrayList arraylist = ... // myobject data list ArrayList temp = (ArrayList)arraylist.Clone(); foreach (var item in temp) { if (...) arraylist.Remove(item); }
Comments