System.InvalidOperationException – Collection was modified; enumeration operation may not execute

Loading

The System.InvalidOperationException – Collection was modified; enumeration operation may not execute is a runtime exception in C# that occurs when you modify a collection (e.g., add, remove, or update elements) while enumerating over it using a foreach loop or an enumerator. This typically happens when:

  1. You modify the collection (e.g., add or remove elements) while iterating over it.
  2. You use an enumerator that becomes invalid after the collection is modified.

Here’s how you can troubleshoot and fix this issue:


1. Avoid Modifying Collections During Enumeration

  • Do not modify the collection (e.g., add, remove, or update elements) while iterating over it. Example:
   List<int> numbers = new List<int> { 1, 2, 3 };
   foreach (int number in numbers)
   {
       if (number == 2)
       {
           numbers.Remove(number); // Error: Collection was modified
       }
   }

Fix:

   List<int> numbers = new List<int> { 1, 2, 3 };
   for (int i = numbers.Count - 1; i >= 0; i--) // Iterate backward to safely remove elements
   {
       if (numbers[i] == 2)
       {
           numbers.RemoveAt(i); // Safe: Modify collection outside of enumeration
       }
   }

2. Use a Copy of the Collection

  • Create a copy of the collection and iterate over the copy while modifying the original collection. Example:
   List<int> numbers = new List<int> { 1, 2, 3 };
   foreach (int number in numbers.ToList()) // Create a copy of the list
   {
       if (number == 2)
       {
           numbers.Remove(number); // Safe: Modify original collection
       }
   }

3. Use a Separate Collection for Modifications

  • Store the elements to be modified in a separate collection and apply the changes after the enumeration. Example:
   List<int> numbers = new List<int> { 1, 2, 3 };
   List<int> toRemove = new List<int>();

   foreach (int number in numbers)
   {
       if (number == 2)
       {
           toRemove.Add(number); // Store elements to remove
       }
   }

   foreach (int number in toRemove)
   {
       numbers.Remove(number); // Modify collection after enumeration
   }

4. Use for Loops Instead of foreach

  • Use a for loop to iterate over the collection and modify it safely. Example:
   List<int> numbers = new List<int> { 1, 2, 3 };
   for (int i = 0; i < numbers.Count; i++)
   {
       if (numbers[i] == 2)
       {
           numbers.RemoveAt(i); // Safe: Modify collection using index
           i--; // Adjust index after removal
       }
   }

Example of Correct Code

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main(string[] args)
    {
        // Example 1: Avoid modifying collections during enumeration
        List<int> numbers = new List<int> { 1, 2, 3 };
        for (int i = numbers.Count - 1; i >= 0; i--) // Iterate backward
        {
            if (numbers[i] == 2)
            {
                numbers.RemoveAt(i); // Safe: Modify collection outside of enumeration
            }
        }
        Console.WriteLine(string.Join(", ", numbers)); // Output: 1, 3

        // Example 2: Use a copy of the collection
        List<int> numbers2 = new List<int> { 1, 2, 3 };
        foreach (int number in numbers2.ToList()) // Create a copy
        {
            if (number == 2)
            {
                numbers2.Remove(number); // Safe: Modify original collection
            }
        }
        Console.WriteLine(string.Join(", ", numbers2)); // Output: 1, 3

        // Example 3: Use a separate collection for modifications
        List<int> numbers3 = new List<int> { 1, 2, 3 };
        List<int> toRemove = new List<int>();

        foreach (int number in numbers3)
        {
            if (number == 2)
            {
                toRemove.Add(number); // Store elements to remove
            }
        }

        foreach (int number in toRemove)
        {
            numbers3.Remove(number); // Modify collection after enumeration
        }
        Console.WriteLine(string.Join(", ", numbers3)); // Output: 1, 3

        // Example 4: Use 'for' loops instead of 'foreach'
        List<int> numbers4 = new List<int> { 1, 2, 3 };
        for (int i = 0; i < numbers4.Count; i++)
        {
            if (numbers4[i] == 2)
            {
                numbers4.RemoveAt(i); // Safe: Modify collection using index
                i--; // Adjust index after removal
            }
        }
        Console.WriteLine(string.Join(", ", numbers4)); // Output: 1, 3
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *