I’m trying to write an extension method in .NET that will operate on a generic collection, and remove all items from the collection that match a given criteria.
This was my first attempt:
public static void RemoveWhere<T>(this ICollection<T> Coll, Func<T, bool> Criteria){ foreach (T obj in Coll.Where(Criteria)) Coll.Remove(obj); }
However this throws an InvalidOperationException, ‘Collection was modified; enumeration operation may not execute’. Which does make sense, so I made a second attempt with a second collection variable to hold the items that need to be removed and iterate through that instead:
public static void RemoveWhere<T>(this ICollection<T> Coll, Func<T, bool> Criteria){ List<T> forRemoval = Coll.Where(Criteria).ToList(); foreach (T obj in forRemoval) Coll.Remove(obj); }
This throws the same exception; I’m not sure I really understand why as ‘Coll’ is no longer the collection being iterated over, so why can’t it be modified?
If anyone has any suggestions as to how I can get this to work, or a better way to achieve the same, that’d be great.
Thanks.
For
List<T>, this exists already, asRemoveAll(Predicate<T>). As such, I’d suggest that you keep the name (allowing familiarity, and precedence).Basically, you can’t remove while iterating. There are two common options:
for) and removalforeach(as you’ve already done)So perhaps:
Or more generally for any
ICollection<T>:This approach has the advantage of avoiding lots of extra copies of the list.