A common coding pattern is removing items from a collection based on the value of the items. The simplest way to do this is to enumerate the collection, and remove all the items that you don't want.
However, doing this will throw this exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute. It seems that the enumerator is invalid after the collection has been modified.
There are several ways to work around this behavior.
1 Store the items to be removed in a temporary collection
This approach is really simple: instead of immedeately removing the items, we keep them in a separate collection. In the end, after the original list has been enumerated, we remove all these items.
In most situations this approach works very well. Only in very large collections, the itemsToRemove collection may become very big and consume a lot of memory. In my experience this is seldom the case.
2 Iterate the collection from back to front
This alternative uses a for-loop to iterate the collection from the back to the front.
Here we do not need a temporary collection. It is also slightly more efficient because we can remove the item based on its index. This means that the collection does not have to search for the item that has to be removed (as was the case in the first approach).
3 Using a predicate
The third alternative is only available from .NET 2 onwards. The List-collection implements a RemoveAll() method that takes a predicate as a parameter. Simply put, a predicate is a delegate that is used for filtering. In this case, the predicate returns true for each item that needs to be removed.
In this code example, the predicate is implemented as an anonymous method:
This approach has some benefits:
- It is self-documenting.
- We don’t have to worry about the performance, we can assume that the RemoveAll() method is implemented in the most efficient way. If the internals of the collection-class would later change, the RemoveAll() method will likely be changed as well to keep the best performance.