78 votes

La collection C# a été modifiée ; l'opération d'énumération ne peut pas être exécutée.

J'essaie de supprimer un élément d'une ArrayList et j'obtiens cette exception :
Collection was modified; enumeration operation may not execute.
Des idées ? Merci pour votre aide

192voto

Marc Gravell Points 482669

Vous retirez l'article pendant une foreach Oui ? Tout simplement, vous ne pouvez pas. Il y a quelques options communes ici :

  • utiliser List<T> et RemoveAll avec un prédicat

  • itérer en arrière par index, en supprimant les éléments correspondants

    for(int i = list.Count - 1; i >= 0; i--) {
        if({some test}) list.RemoveAt(i);
    }
  • utiliser foreach et place les éléments correspondants dans une deuxième liste ; maintenant, énumère la deuxième liste et supprime ces éléments de la première (si vous voyez ce que je veux dire).

24voto

Will Points 597

Voici un exemple (désolé pour les fautes de frappe)

var itemsToRemove = new ArrayList();  // should use generic List if you can

foreach (var item in originalArrayList) {
  if (...) {
    itemsToRemove.Add(item);
  }
}

foreach (var item in itemsToRemove) {
  originalArrayList.Remove(item);
}

OU si vous utilisez la version 3.5, Linq rend la première partie plus facile :

itemsToRemove = originalArrayList
  .Where(item => ...)
  .ToArray();

foreach (var item in itemsToRemove) {
  originalArrayList.Remove(item);
}

Remplacez "..." par votre condition qui détermine si l'élément doit être retiré.

8voto

ozczecho Points 3575

Une façon de procéder consiste à ajouter le ou les éléments à supprimer à une nouvelle liste. Ensuite, passez en revue et supprimez ces éléments.

8voto

Joe B Points 108

J'aime bien itérer en arrière en utilisant une for mais cela peut devenir fastidieux comparé à foreach . Une solution que j'apprécie est de créer un énumérateur qui parcourt la liste en sens inverse. Vous pouvez l'implémenter comme une méthode d'extension sur ArrayList ou List<T> . La mise en œuvre pour ArrayList est ci-dessous.

    public static IEnumerable GetRemoveSafeEnumerator(this ArrayList list)
    {
        for (int i = list.Count - 1; i >= 0; i--)
        {
            // Reset the value of i if it is invalid.
            // This occurs when more than one item
            // is removed from the list during the enumeration.
            if (i >= list.Count)
            {
                if (list.Count == 0)
                    yield break;

                i = list.Count - 1;
            }

            yield return list[i];
        }
    }

La mise en œuvre pour List<T> est similaire.

    public static IEnumerable<T> GetRemoveSafeEnumerator<T>(this List<T> list)
    {
        for (int i = list.Count - 1; i >= 0; i--)
        {
            // Reset the value of i if it is invalid.
            // This occurs when more than one item
            // is removed from the list during the enumeration.
            if (i >= list.Count)
            {
                if (list.Count == 0)
                    yield break;

                i = list.Count - 1;
            }

            yield return list[i];
        }
    }

L'exemple ci-dessous utilise l'énumérateur pour supprimer tous les nombres entiers pairs d'un fichier de type ArrayList .

    ArrayList list = new ArrayList() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    foreach (int item in list.GetRemoveSafeEnumerator())
    {
        if (item % 2 == 0)
            list.Remove(item);
    }

5voto

David Lively Points 16026

Ne modifiez pas la liste à l'intérieur d'une boucle qui itère dans la liste.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X