Introduction: Meet the error that has broken code millions of times
Have you ever written a simple foreach, run the program, and suddenly — bam! — an InvalidOperationException pops up with the frightening message: "Collection was modified; enumeration operation may not execute"? If so, you are not alone. This question on Stack Overflow has gathered thousands of views, and it is asked by both beginners and experienced developers.
In this article, we will break down why this error occurs, how to reproduce it, and most importantly — how to avoid it. We will look at three proven methods, write real C# code, and give you a clear action plan. Let's go!
What is "Collection was modified"? Error analysis
The error Collection was modified; enumeration operation may not execute is an exception of type InvalidOperationException that is thrown when you try to modify a collection (add, remove, or replace an element) while iterating over it using foreach or another enumerator (IEnumerator).
Imagine you are reading a book, and someone simultaneously tears pages out of it. You get lost, not knowing what to read next. That's exactly how the enumerator feels: it doesn't know how to continue if the collection changes on the fly.
What does the code that causes the error look like?
Here is a classic example that is guaranteed to lead to an error:
List<string> fruits = new List<string> { "apple", "banana", "cherry", "date" };
foreach (var fruit in fruits){ if (fruit == "banana") { fruits.Remove(fruit); // Error! Collection was modified }}Run this code — and you will get an InvalidOperationException on the second iteration. Why? Because foreach uses an internal enumerator that blocks collection modifications during traversal.
Why does this happen? Let's look under the hood of C#
When you write foreach, the C# compiler transforms it into a call to the GetEnumerator() method. This method returns an IEnumerator object that stores the traversal state (current index, collection version). Every time the collection is modified (via Add, Remove, Clear, etc.), its internal version counter is incremented. The enumerator checks this version at each step. If it doesn't match — an exception is thrown.
This is done to protect against undefined behavior. Imagine you remove an element from the middle of a list: the indices of all subsequent elements shift, and the enumerator might skip an element or process the same one twice. The .NET developers decided it was better to throw an exception than to allow an unnoticed logical error.
Top 3 ways to avoid the "Collection was modified" error
Now that we know the enemy, let's figure out how to defeat it. There are three main approaches, and each is suitable for different situations.
Method 1: Copying the collection before iteration
The simplest and safest method is to create a copy of the collection and iterate over it, while making changes to the original.
List<string> fruits = new List<string> { "apple", "banana", "cherry", "date" };
// Create a copy of the list for iterationforeach (var fruit in fruits.ToList()) // or new List<string>(fruits){ if (fruit == "banana") { fruits.Remove(fruit); // Now this is safe }}
Console.WriteLine(string.Join(", ", fruits)); // Output: apple, cherry, datePros: Simplicity, readability, suitable for small collections.
Cons: Requires additional memory, can be slow for large lists.
Tip: Me