I’m sure one of the first exceptions any of us get as C# devs is when we try to iterate over a List (or other enumerable) and attempt to remove an item.
List<SomeObscureObject> objectsToBeFiltered = new List <SomeObscureObject>();
objectsToBeFiltered.Add(new SomeObscureObject{SomeObscureProperty = "Object 1"});
objectsToBeFiltered.Add(new SomeObscureObject{SomeObscureProperty = "Object 2"});
objectsToBeFiltered.Add(new SomeObscureObject{SomeObscureProperty = "Object 3"});
objectsToBeFiltered.Add(new SomeObscureObject{SomeObscureProperty = "Object 4"});
foreach (var obscureObject in objectsToBeFiltered)
{
if(obscureObject.SomeObscureProperty == valueToBeRemoved)
objectsToBeFiltered.Remove(obscureObject);
}
This results in the exception:
InvalidOperationException was unhandled. Collection was modified; enumeration operation may not execute.
The easy solution is just to create a temp collection, add the items to the temporary collection, and then remove them from the main collection. This seems so common that I just never thought there may be another solution.
List<SomeObscureObject> objectsToRemove = new List <SomeObscureObject>();
foreach (var obscureObject in objectsToBeFiltered)
{
if(obscureObject.SomeObscureProperty == valueToBeRemoved)
objectsToRemove.Add(obscureObject);
}
foreach (var obscureObject in objectsToRemove)
{
objectsToBeFiltered.Remove(obscureObject);
}
While recently reading Eric Lippert’s blog I ended up down a rabbit hole to another blog where the blogger talked on this very same issue. Did you know that if you iterate over the collection backwards you won’t get this exception :).
for(int i = objectsToBeFiltered.Count - 1; i >= 0; i--)
{
SomeObscureObject objectToCheck = objectsToBeFiltered[i];
if(objectToCheck.SomeObscureProperty == valueToBeRemoved)
objectsToBeFiltered.Remove(objectToCheck);
}
To read a few more suggestions head over to this post. There is also another great alternative using LINQ.
Thanks,
Brian