Skip to content

Instantly share code, notes, and snippets.

@jakedowns
Created December 20, 2023 17:32
Show Gist options
  • Save jakedowns/10e2b9c402ff1aa498155c4fb474acf2 to your computer and use it in GitHub Desktop.
Save jakedowns/10e2b9c402ff1aa498155c4fb474acf2 to your computer and use it in GitHub Desktop.
how to fix foreach InvalidOperationException

In Unity, when dealing with object pools or any collection from which you need to remove objects during iteration, it's indeed important to be careful about how you modify the collection. Modifying a collection while iterating over it using a foreach loop can indeed cause exceptions, specifically an InvalidOperationException because the collection is modified during its enumeration.

There are a few strategies to safely remove items from a collection while iterating over it:

  1. Backwards for Loop: As you mentioned, using a traditional for loop and iterating backwards is a common and effective way. This method is especially useful for lists or arrays where removing an item shifts the indices of subsequent items. By iterating backwards, you ensure that the removal of an item doesn't affect the indices of the items you haven't processed yet.

    for (int i = collection.Count - 1; i >= 0; i--)
    {
        // Perform removal logic
        if (ShouldRemove(collection[i]))
        {
            collection.RemoveAt(i);
        }
    }
  2. Using a while Loop: Another approach is to use a while loop that removes items from the beginning of the collection until it's empty. This is effective but might be less efficient if the collection is a list or an array, as removing elements from the beginning usually involves shifting all other elements.

    while (collection.Count > 0)
    {
        // Remove first element or based on some condition
        collection.RemoveAt(0);
    }
  3. Temporary List for Removal: You can create a temporary list to keep track of items to be removed and then remove those items in a separate step. This avoids modifying the collection while iterating over it.

    List<T> itemsToRemove = new List<T>();
    foreach (var item in collection)
    {
        if (ShouldRemove(item))
        {
            itemsToRemove.Add(item);
        }
    }
    
    foreach (var item in itemsToRemove)
    {
        collection.Remove(item);
    }
  4. for Loop with Forward Iteration: You can also use a forward iterating for loop, but you need to adjust the index when you remove an item to avoid skipping the next item.

    for (int i = 0; i < collection.Count; i++)
    {
        if (ShouldRemove(collection[i]))
        {
            collection.RemoveAt(i);
            i--; // Decrement index to adjust for the removed item
        }
    }

Each of these methods has its own pros and cons, and the best approach depends on the specific circumstances of your application, such as the type of collection you're using and the nature of the removal conditions. For most cases, the backwards for loop is a straightforward and efficient choice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment