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
Réponses
Trop de publicités?Vous retirez l'article pendant une foreach
Oui ? Tout simplement, vous ne pouvez pas. Il y a quelques options communes ici :
-
utiliser
List<T>
etRemoveAll
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).
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é.
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);
}