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