Collection was modified; enumeration operation may not execute in ArrayList

C#ExceptionCollectionsEnumeration

C# Problem Overview


I'm trying to remove an item from an ArrayList and I get this Exception:
Collection was modified; enumeration operation may not execute.

Any ideas?

C# Solutions


Solution 1 - C#

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)

Solution 2 - C#

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.

Solution 3 - C#

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

Solution 4 - C#

I like to iterate backward using a for loop, but this can get tedious compared to foreach. One solution I like is to create an enumerator that traverses the list backward. You can implement this as an extension method on ArrayList or List<T>. The implementation for ArrayList is below.

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

The implementation for List<T> is similar.

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

The example below uses the enumerator to remove all even integers from an 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);
    }

Solution 5 - C#

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

Instead, use a for() or while() with an index, going backwards through the list. (This will let you delete things without getting an invalid index.)

var foo = new List<Bar>();

for(int i = foo.Count-1; i >= 0; --i)
{
  var item = foo[i];
  // do something with item
}

Solution 6 - C#

Am I missing something? Somebody correct me if I'm wrong.

list.RemoveAll(s => s.Name == "Fred");

Solution 7 - C#

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

Solution 8 - C#

I agree with several of the points I've read in this post and I've incorporated them into my solution to solve the exact same issue as the original posting.

That said, the comments I appreciated are:

  • "unless you are using .NET 1.0 or 1.1, use List<T> instead of ArrayList. "

  • "Also, add the item(s) to be deleted to a new list. Then go through and delete those items." .. in my case I just created a new List and the populated it with the valid data values.

e.g.

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

Solution 9 - C#

using ArrayList also you can try like this

ArrayList arraylist = ... // myobject data list

ArrayList temp = (ArrayList)arraylist.Clone();
                                            
foreach (var item in temp)
{
      if (...)
         arraylist.Remove(item);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRicardoView Question on Stackoverflow
Solution 1 - C#Marc GravellView Answer on Stackoverflow
Solution 2 - C#WillView Answer on Stackoverflow
Solution 3 - C#ozczechoView Answer on Stackoverflow
Solution 4 - C#Joe BView Answer on Stackoverflow
Solution 5 - C#3DaveView Answer on Stackoverflow
Solution 6 - C#KevinDeusView Answer on Stackoverflow
Solution 7 - C#Seva AlekseyevView Answer on Stackoverflow
Solution 8 - C#Brian WellsView Answer on Stackoverflow
Solution 9 - C#Nikson Kanti PaulView Answer on Stackoverflow