tags:

views:

593

answers:

5

Hi there.
I'm trying to remove a item from a ArrayList and I get this Exception:
Collection was modified; enumeration operation may not execute.
Any ideas? thanks for the help

+1  A: 

Don't modify the list inside of a loop which iterates through the list.

David Lively
Snap! So, how should i be doing it?
Ricardo
Use a regular loop instead (for/while). The problem is using a 'foreach' statement (i.e. an enumerator).
Noon Silk
@silky f you're using a for() or while() to iterate through the collection, be sure to do it from the back/top - starting at collection.count-1 and going down to 0. Otherwise you'll hit the same problem.
David Lively
+19  A: 

You are removing the item during a foreach, yes? Simply, you can't. There are a few common options here:

  • use List<T> and RemoveAll with a predicate
  • iterate backwards by index, removing matching items

    for(int i = list.Count - 1; i >= 0; i--) {
        if({some test}) list.RemoveAt(i);
    }
    
  • use foreach, and put matching items into a second list; now enumerate the second list and remove those items from the first (if you see what I mean)

Marc Gravell
+1, too quick for me :)
Glenn Condron
I see what you mean... i'll try to do it
Ricardo
if the collection isn't that big, a simple .ToArray() and enumerating that instead might be good enough as well.
Lasse V. Karlsen
Thank you my good sir
Ricardo
That's pretty neat, ive always been iterating forwards and conditionally decrementing `i` so that next time it increments it will point to the item after the deleted one. This avoids the extra step.
Igor Zevaka
Backwards iteration works fine. I'd avoid using .ToArray() as it adds an unnecessary loop to your algorithm (one to copy the list to an array, one to remove the items you're interested in).
David Lively
A: 

Instead of foreach(), use a for() loop with a numeric index.

Seva Alekseyev
You *must* count backwards if you use this approach though.
Rob Levine
@Rob - not *must*, but it is trickier if you go forwards; more ways to get it wrong and end up off-by-one.
Marc Gravell
A: 

One way is to add the item(s) to be deleted to a new list. Then go through and delete those items.

ozczecho
+2  A: 

Here's an example (sorry for any typos)

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

OR if you're using 3.5, Linq makes the first bit easier:

itemsToRemove = originalArrayList
  .Where(item => ...)
  .ToArray();

foreach (var item in itemsToRemove) {
  originalArrayList.Remove(item);
}

Replace "..." with your condition that determines if item should be removed.

Will
If you're using "generic List" (which I interpret as `List<T>`) then just use `list.RemoveAll(item => ...)`.
Marc Gravell