It's dangerous to code alone! Take this.

Lists and Invalid Operation Exceptions

On page 244, while discussing the List<T> type and foreach loops, it indicates that if you modify a list (add, remove, replace items) while doing a foreach loop, you will get an InvalidOperationException. The book states that there are “two workarounds for this” and then describes only one. This article covers the second workaround in a bit of depth.

While there are probably other workarounds than these, they are the two I used the most.

Workaround #1 is to use a for loop instead, and then make sure that as you add and remove items from the list, you correctly maintain your index variable used in the for loop.

Workaround #2 is this:

When you detect that you need to add or remove items to the collection, rather than modifying the collection immediately, you defer the addition or removal until after the foreach loop. Make a note of what items need to be added or removed, and then once the foreach loop is complete, you add all the items you needed to add and remove all the items you no longer want.

A simple way to do this is by having two other lists that contain the items to add and the items to remove:

List<Something> mainList = ...; // This is actually usually a field or a parameter or something, rather than a local variable.

List<Something> toAdd = new List<Something>();
List<Something> toRemove = new List<Something>();

foreach (Something thing in mainList)
{
    if (/* detect a deletion */)
        toRemove.Add(thing);
    if(/* detect an addition */)
        toAdd.Add(new Something());

    // Do more work in the loop.
}

foreach (Something add in toAdd) // Or call `mainList.AddRange(toAdd);`
    mainList.Add(add);

foreach(Something remove in toRemove)
    mainList.Remove(remove);

With code like this, you are never changing a collection that you are currently iterating over, and the problem is solved.

This isn’t the only way to implement this strategy. For example, I’ve seen some game code where the list you’re iterating over is a collection of some base class for all objects in the game, like a GameObject class, and where this class has an IsAlive property. In such a scenario, you could skip the toRemove list entirely, and when you detect the removal of the object, you set IsAlive to false. (If you’re doing that, there’s a method on List<T> called RemoveWhere that takes a delegate (Level 36, but also look at lambdas in Level 38) that would make short work of removing all items in the list whose IsAlive property is false: mainList.RemoveWhere(t => !t.IsAlive);.)