CodeGym /Cours /C# SELF /Suppression d’un élément d’une collection dans une boucle...

Suppression d’un élément d’une collection dans une boucle foreach

C# SELF
Niveau 29 , Leçon 4
Disponible

1. Introduction

Quasiment tout le monde qui débute en C# tombe tôt ou tard sur le même souci : t’as une collection (genre une liste d’objets) et tu veux virer les éléments inutiles selon une condition. Ça a l’air simple, et t’as envie d’utiliser la boucle foreach que tu connais bien, parce que c’est le moyen le plus “safe” et “friendly” de parcourir une collection. Mais là, bim, au moment où tu t’y attends le moins, tu te prends une erreur d’exécution chelou qui n’arrivait pas dans les exemples simples — et ton programme s’arrête net.

On va voir ensemble pourquoi ça arrive, ce qui se passe “sous le capot” avec les collections et les itérateurs, et comment supprimer des éléments proprement pour éviter les surprises et les bugs.

Pourquoi foreach n’aime pas la suppression d’éléments

Pour bien piger le truc, imagine une file d’attente de gens (c’est notre collection). Tu passes dans la file et tu demandes à chacun : "Je te garde ou je t’efface ?" Si tu commences à barrer des gens pendant que tu parcours la file, tout le monde se décale, les gens bougent, et ton plan “la personne suivante = la suivante dans la liste” part en vrille. Tu risques d’en zapper certains ou d’en interroger d’autres deux fois.

Exemple en C# :


List<string> noms = new List<string> { "Anton", "Boris", "Vika", "Gricha" };

foreach (string nom in noms)
{
    if (nom.StartsWith("V"))
        noms.Remove(nom); // Boom ! InvalidOperationException
}

Quand le programme arrive à "Vika" et veut la supprimer, l’itérateur interne perd “le contact avec la réalité” — et tu reçois ce message :
InvalidOperationException: Collection was modified; enumeration operation may not execute.

C’est pas juste pour t’embêter — c’est la façon dont C# te protège des bugs galères et des structures de données pétées.

2. Pourquoi ce code tout simple ne marche pas ?

Comment ça marche à l’intérieur ?

Quand tu écris une boucle foreach, le compilateur génère un objet spécial — un itérateur (IEnumerator), qui garde la position actuelle dans la collection. Cet objet se souvient du nombre d’éléments au départ, de l’élément “actif” et il vérifie à fond que la collection ne change pas pendant le parcours.

Toute tentative de supprimer ou d’ajouter un élément dans foreach casse ce contrat. Pourquoi ? Si tu vires un élément, les index bougent, et l’itérateur ne peut plus passer au suivant correctement. Tu risques d’en zapper, d’en traiter deux fois — bref, c’est le bazar. Donc dès que tu modifies la collection, .NET balance une erreur cash.

Ce qui se passe si tu supprimes “à l’arrache”

Imagine que t’as écrit ce programme :


List<int> nombres = new List<int> { 1, 2, 3, 4, 5, 6 };
foreach (int x in nombres)
{
    if (x % 2 == 0)
        nombres.Remove(x);
}

Ça paraît logique : tu parcours tous les nombres, tu vires les pairs. Mais au deuxième tour, le programme balance une erreur — “collection modifiée pendant l’énumération”.

Parfois, t’as envie de contourner l’avertissement et de tenter le coup “à tes risques et périls”. Mais même sans erreur, selon la structure de la collection, le résultat serait imprévisible. Tu pourrais sauter des éléments ou ne pas tous les supprimer.

3. Alors, comment faire bien ?

Technique n°1 : Boucle for à l’envers

Le souci, c’est qu’en supprimant, tu “décales” les éléments suivants à gauche, et si tu pars du début, tu risques de te planter dans les index et d’en zapper. Pour éviter ça, pars de la fin.


List<string> noms = new List<string> { "Anton", "Boris", "Vika", "Gricha" };

for (int i = noms.Count - 1; i >= 0; i--)
{
    if (noms[i].StartsWith("V"))
        noms.RemoveAt(i);
}

Ici, après chaque suppression, tous les éléments après celui supprimé se décalent, mais les index qu’on n’a pas encore traités restent bons. Du coup, rien n’est zappé.

Technique n°2 : Filtrer, créer une nouvelle liste

Parfois, c’est plus simple (et souvent plus rapide) de parcourir la collection, de garder que les éléments à conserver, et de remplacer la liste d’origine par la nouvelle.


var noms = new List<string> { "Anton", "Boris", "Vika", "Gricha" };
noms = noms.Where(nom => !nom.StartsWith("V")).ToList();
// À la fin, il reste "Anton" et "Gricha"

Cette méthode est cool si la collection n’est pas énorme ou si tu t’en fiches de garder la référence d’origine.

Technique n°3 : Utiliser les méthodes spéciales des collections

Si tu bosses avec un List<T> classique, pour supprimer selon une condition, t’as une méthode pratique :


noms.RemoveAll(nom => nom.StartsWith("V"));

Tout est géré proprement à l’intérieur, et ton code reste clean et lisible.

Technique n°4 : Préparer la suppression

Y’a des collections qu’on peut pas modifier “à la volée” (genre Dictionary, HashSet, ou même ta propre classe). Dans ces cas-là, on fait comme ça :

  1. D’abord, tu parcours la collection et tu mets tous les éléments à supprimer dans une liste à part.
  2. Ensuite, tu parcours cette nouvelle liste et tu vires les éléments de la collection d’origine.

Dictionary<int, string> dico = new Dictionary<int, string> { [1] = "un", [2] = "deux", [3] = "trois" };
var aSupprimer = new List<int>();
foreach (var kvp in dico)
{
    if (kvp.Key % 2 == 0)
        aSupprimer.Add(kvp.Key);
}
foreach (var cle in aSupprimer)
    dico.Remove(cle);

4. Quelques détails utiles

Erreurs et mythes des débutants

Une des erreurs les plus courantes — croire que supprimer un élément d’une collection pendant le parcours va “marcher quand même”, parce que dans d’autres langages (genre Python) ça passe souvent. Mais en C#, c’est strictement interdit pour ta sécurité : mieux vaut une erreur claire qu’un bug sournois impossible à retrouver.

Autre erreur fréquente — utiliser une boucle for en augmentant l’index au lieu de le diminuer. Résultat : après une suppression, tout se décale et tu zappes des éléments. Va toujours de la fin vers le début si tu supprimes par index.

La morale de l’histoire

La mission “supprimer des éléments d’une collection selon une condition” arrive dans un programme C# sur deux, mais le faire direct dans une boucle foreach c’est mort — c’est l’architecture du langage, pour garantir l’intégrité de tes données et éviter les bugs surprises.
Garde cette règle en tête, ça t’évitera des nuits blanches avec le debugger.

Comment faire toujours bien

  • Ne supprime jamais d’éléments d’une collection direct dans une boucle foreach. Ça va planter à l’exécution.
  • Pour les listes (List<T>) et les tableaux, utilise soit une boucle for à l’envers, soit les méthodes RemoveAll ou la filtration avec LINQ.
  • Pour les dictionnaires, ensembles et autres collections complexes — commence par lister les éléments à supprimer, puis parcours cette liste pour les virer de la collection d’origine.
  • Si t’es pas sûr — demande-toi : qu’est-ce qui change dans la collection quand je supprime ? Comment va réagir l’itérateur ? Si t’as le moindre doute, c’est que c’est pas la bonne méthode.
1
Étude/Quiz
Filtrage des éléments, niveau 29, leçon 4
Indisponible
Filtrage des éléments
Travailler avec des collections
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION