Comment supprimer de manière conditionnelle des éléments d'une collection .NET
Je suis en train d'écrire une méthode d'extension .NET qui va fonctionner sur une collection générique, et supprimer tous les éléments de la collection qui correspondent à un critère donné.
C'était ma première tentative:
public static void RemoveWhere<T>(this ICollection<T> Coll, Func<T, bool> Criteria){
foreach (T obj in Coll.Where(Criteria))
Coll.Remove(obj);
}
Toutefois, cela déclenche une exception InvalidOperationException, "la Collection a été modifiée; opération d'énumération peut pas exécuter". Ce qui est logique, j'ai donc fait une deuxième tentative avec un deuxième prélèvement variable pour contenir les éléments qui doivent être enlevés et itérer qu'au lieu:
public static void RemoveWhere<T>(this ICollection<T> Coll, Func<T, bool> Criteria){
List<T> forRemoval = Coll.Where(Criteria).ToList();
foreach (T obj in forRemoval)
Coll.Remove(obj);
}
Ce lève la même exception; je ne suis pas sûr de vraiment comprendre pourquoi 'Coll' n'est plus la collection en cours de itéré, alors pourquoi ne peut-il pas être modifié?
Si quelqu'un a des suggestions sur comment je peux obtenir que cela fonctionne, ou une meilleure façon d'obtenir les mêmes, ce serait sympa.
Grâce.
source d'informationauteur Lee D
Vous devez vous connecter pour publier un commentaire.
Pour
List<T>
cela existe déjà, commeRemoveAll(Predicate<T>)
. En tant que tel, je vous suggère de que vous garder le nom (permettant la familiarité et la précédence).Fondamentalement, vous ne pouvez pas supprimer lors de l'itération. Il y a deux options:
for
) et la suppressionforeach
(comme vous l'avez déjà fait)Donc peut-être:
Ou plus généralement pour toute
ICollection<T>
:Cette approche a l'avantage d'éviter beaucoup de copies supplémentaires de la liste.
Comme Marc l'a dit,
List<T>.RemoveAll()
est le chemin à parcourir pour les listes.Je suis surpris de votre deuxième version n'a pas fonctionner, cependant, étant donné que vous avez reçu l'appel à
ToList()
après laWhere()
appel. Sans leToList()
appel il serait certainement faire sens (parce qu'il serait évalué paresseusement), mais ça devrait être bon comme il est. Pourriez-vous montrer un court mais complet exemple de cet échec?EDIT: Concernant votre commentaire sur la question, je ne peux toujours pas le faire échouer. Voici une courte mais complète exemple qui fonctionne:
Si vous pouvez fournir un semblable complète exemple, qui ne parvient pas, je suis sûr que nous pouvons travailler sur la raison.
Je l'ai juste testé, et votre deuxième méthode fonctionne très bien (comme il se doit). Autre chose doit aller mal, vous pouvez donner un peu d'exemple de code qui montre le problème?
Obtient:
J'ai juste essayé votre deuxième exemple et il semble bien fonctionner:
Je n'ai pas une exception.
Une autre version de Marcs RemoveAll: