Collection foi modificada: como vencer o erro de iteração de coleções

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Conheça o erro que quebrou códigos milhões de vezes



Você já escreveu um simples foreach, executou o programa e, de repente — bum! — aparece um InvalidOperationException com a mensagem assustadora: "Collection was modified; enumeration operation may not execute"? Se sim, você não está sozinho. Esta pergunta no Stack Overflow acumulou milhares de visualizações, e é feita tanto por iniciantes quanto por desenvolvedores experientes.



Neste artigo, vamos analisar por que esse erro ocorre, como reproduzi-lo e, o mais importante, como evitá-lo. Veremos três formas comprovadas, escreveremos código real em C# e daremos a você um plano de ação claro. Vamos lá!



O que é "Collection was modified"? Análise do erro



O erro Collection was modified; enumeration operation may not execute é uma exceção do tipo InvalidOperationException que é lançada quando você tenta modificar uma coleção (adicionar, remover ou substituir um elemento) durante sua iteração com foreach ou outro enumerador (IEnumerator).



Imagine que você está lendo um livro e alguém arranca páginas dele ao mesmo tempo. Você se perde, não sabe o que ler em seguida. Assim também funciona o enumerador: ele não sabe como continuar se a coleção muda durante a execução.



Como é o código que causa o erro?

Aqui está um exemplo clássico que certamente levará ao erro:



List<string> fruits = new List<string> { "apple", "banana", "cherry", "date" };

foreach (var fruit in fruits){ if (fruit == "banana") { fruits.Remove(fruit); // Erro! Collection was modified }}


Execute este código — e você obterá InvalidOperationException na segunda iteração. Por quê? Porque o foreach usa um enumerador interno que bloqueia alterações na coleção durante a iteração.



Por que isso acontece? Uma olhada nos bastidores do C#



Quando você escreve foreach, o compilador C# o converte em uma chamada ao método GetEnumerator(). Este método retorna um objeto IEnumerator que armazena o estado da iteração (índice atual, versão da coleção). Cada vez que a coleção é modificada (via Add, Remove, Clear, etc.), seu contador interno de versão é incrementado. O enumerador verifica essa versão a cada passo. Se não coincidir — a exceção é lançada.



Isso foi feito para proteção contra comportamento indefinido. Imagine que você remove um elemento do meio da lista: os índices de todos os elementos subsequentes são deslocados, e o enumerador pode pular um elemento ou processar o mesmo duas vezes. Os desenvolvedores do .NET decidiram que é melhor lançar uma exceção do que permitir um erro lógico imperceptível.



Top 3 formas de evitar o erro "Collection was modified"



Agora que conhecemos o inimigo de vista, vamos analisar como vencê-lo. Existem três abordagens principais, e cada uma é adequada para diferentes situações.



Forma 1: Copiar a coleção antes da iteração

O método mais simples e seguro — criar uma cópia da coleção e iterar sobre ela, enquanto as modificações são feitas no original.



List<string> fruits = new List<string> { "apple", "banana", "cherry", "date" };

// Criamos uma cópia da lista para iteraçãoforeach (var fruit in fruits.ToList()) // ou new List<string>(fruits){ if (fruit == "banana") { fruits.Remove(fruit); // Agora é seguro }}

Console.WriteLine(string.Join(", ", fruits)); // Saída: apple, cherry, date


Vantagens: Simplicidade, legibilidade, adequado para coleções pequenas.
Desvantagens: Requer memória adicional, pode ser lento para listas grandes.



Dica: Me

Blogs

Book Recommendations