2 votes

Meilleure façon d'énumérer une collection lorsque des éléments peuvent être supprimés pendant l'énumération

Il existe une collection typique de certains objets de classe, par exemple string pour une simplicité

IList collection = new List();

Pendant le déroulement du programme, certaines fonctions doivent opérer sur la collection, traiter les objets de classe et, en fonction du résultat de l'opération, supprimer l'objet de classe traité de la collection.

Par exemple, dans l'exemple suivant avec des chaînes, si la chaîne est "failed", alors supprimez cet élément

foreach (string str in collection)
{
    // opérer sur l'objet de classe actuel
    // si str n'est pas valide
    if (str == "failed")
        collection.Remove(str);
}

De toutes les manières, cela entraîne une exception. Quel est le meilleur moyen de parcourir tous les éléments en ayant la capacité de les supprimer pendant l'énumération?

5voto

codeulike Points 9017

Faites une boucle for indexée, mais faites-la à l'envers, car lorsque vous supprimez des membres, les index en amont sont modifiés.

par exemple, pour votre exemple de collection de chaînes:

for (int i = collection.Count() - 1; i >= 0; i--)
{
    // faites d'autres choses, puis ...

    if (collection[i] == "failed")
        collection.RemoveAt(i);
}

NB: si vous utilisez une boucle for normale, cela peut sembler fonctionner au début, mais cela sautera un élément après chaque suppression (en raison de la façon dont les index sont renumérotés après une suppression). Ainsi, un symptôme courant de ce bug est que les suppressions semblent fonctionner jusqu'à ce que vous en obteniez deux consécutives. Cela peut être un bug assez déroutant. Pas que cela ne m'ait jamais arrivé *tousse*

1voto

Mongus Pong Points 6902

Pour les collections List<> vous pouvez utiliser RemoveAll.

collection.RemoveAll ( item => item == "failed" );

Pour les collections génériques IEnumerable<> vous pouvez créer une nouvelle collection avec les éléments supprimés.

var newList = collection.Where ( item => item != "failed" );

Comme elle est évaluée de manière paresseuse, vous ne créez pas réellement deux collections en mémoire, mais plutôt une machine d'état qui énumérera les éléments non échoués au besoin.

0voto

adarshr Points 25912

Si la collection est une List ou un Set, vous pouvez utiliser une boucle for indexée et effectuer la suppression.

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