Question

J'ai un api tiers, qui a une classe qui renvoie un recenseur pour les différents éléments de la classe.

Je dois supprimer un élément dans ce recenseur, donc je ne peux pas utiliser « pour chaque ». La seule option que je peux penser est d'obtenir le nombre par itérer sur l'ENUM puis exécutez une boucle normale pour supprimer les éléments.

Quelqu'un sait d'une façon d'éviter les deux boucles?

Merci

[mise à jour] désolé pour la confusion, mais Andrey ci-dessous dans les commentaires est juste.

Voici quelques pseudo-code de ma tête qui ne fonctionnera pas et que je suis à la recherche d'une solution qui n'implique deux boucles, mais je suppose que ce n'est pas possible:

for each (myProperty in MyProperty)
{
if (checking some criteria here)
   MyProperty.Remove(myProperty)
}

MyProperty est la classe de troisième partie qui met en œuvre le recenseur et la méthode de suppression.

Était-ce utile?

La solution

modèle commun est de faire quelque chose comme ceci:

List<Item> forDeletion = new List<Item>();

foreach (Item i in somelist)
   if (condition for deletion) forDeletion.Add(i);

foreach (Item i in forDeletion)
   somelist.Remove(i); //or how do you delete items 

Autres conseils

Boucle à travers une fois et créer un second tableau qui contient les éléments qui ne doivent pas être supprimés.

Si vous savez qu'il est une collection, vous pouvez aller avec pour revenue:

for (int i = items.Count - 1; i >= 0; i--)
{
   items.RemoveAt(i);
}

Dans le cas contraire, vous devrez faire deux boucles.

Vous pouvez créer quelque chose comme ceci:

      public IEnumerable<item> GetMyList()
    {
        foreach (var x in thirdParty )
        {
            if (x == ignore)
                continue;
            yield return x;
        }

    }
  

Je dois supprimer un élément dans ce recenseur

Tant que cela est un élément unique qui est pas un problème. La règle est que vous ne pouvez pas continuer pour itérer après avoir modifié la collection. Ainsi:

foreach (var item in collection) {
    if (item.Equals(toRemove) {
        collection.Remove(toRemove);
        break;      // <== stop iterating!!
    }
}

Il est impossible de supprimer un élément d'un recenseur. Ce que vous pouvez faire est de copier ou d'un filtre (ou les deux) le contenu de la totalité de la séquence d'énumération. Vous pouvez y parvenir en utilisant LINQ et faire qch comme ceci:

   YourEnumerationReturningFunction().Where(item => yourRemovalCriteria);

Pouvez-vous donner des détails sur l'API et les appels API que vous utilisez?

Si vous recevez un IEnumerator<T> ou IEnumerable<T> vous ne pouvez pas supprimer tout élément de la séquence derrière le recenseur, car il n'y a pas de méthode pour le faire. Et vous devez bien sûr pas compter sur le bas en jetant un objet reçu parce que la mise en œuvre peut changer. (En fait, une API bien conçu ne doit pas exposer des objets mutables maintien de l'état interne du tout.)

Si vous recevez IList<T> ou quelque chose de similaire, vous pouvez simplement utiliser une boucle de for normale de l'arrière vers l'avant et supprimer les éléments au besoin, car il n'y a pas iterator qui pourrait être endommagé l'état. (Ici, la règle d'exposer l'état mutable devrait appliquer à nouveau -. Modifier la collection retournée ne devrait pas changer tout état)

IEnumerator.Count () décidera au moment de l'exécution ce qu'il doit faire - Dénombrer compter ou réfléchir pour voir c'est une collection et d'appeler .Count cette façon.

Je aime la suggestion de Sjoerd mais je me inquiète pour le nombre d'articles que nous pouvons parler.

Pourquoi ne pas quelque chose comme ..

 // you don't want 2 and 3
 IEnumerable<int> fromAPI = Enumerable.Range(0, 10);
 IEnumerable<int> result = fromAPI.Except(new[] { 2, 3 });

Une manière propre et lisible pour ce faire est la suivante (je devine à l'API du conteneur tiers ici puisque vous ne l'avez pas spécifié il.)

foreach(var delItem in ThirdPartyContainer.Items
                       .Where(item=>ShouldIDeleteThis(item))
                       //or: .Where(ShouldIDeleteThis)
                       .ToArray()) {
    ThirdPartyContainer.Remove(delItem);
}

L'appel à .ToArray() garantit que tous les éléments à supprimer ont été avidement mis en cache avant l'itération foreach commence.

Dans les coulisses cela implique un tableau et une itération supplémentaire sur, mais qui est généralement très pas cher, et l'avantage de cette méthode par rapport aux autres réponses à cette question est que cela fonctionne sur enumerables plaine et ne concerne pas l'état mutable délicat les questions qui sont difficiles à lire et facile de se tromper.

Par contre, itérer en sens inverse, sans la science des fusées, est beaucoup plus enclin à hors-par une erreur et plus difficile à lire; et il se fonde également sur la collection interne de tels que ne pas changer l'ordre entre les suppressions (par exemple préférable de ne pas être un tas binaire, par exemple). Manuellement ajouter des éléments qui doivent être supprimés à une liste temporaire est tout simplement le code inutile - c'est ce que .ToArray () fera très bien: -.)

un recenseur a toujours un champ privé en montrant la véritable collection.
vous pouvez l'obtenir via reflection.modify il.
vous amuser.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top