9
votes

Exclure les types de formes iEnumerables avec Linq

Comment puis-je filtrer les objets en fonction de leur type dérivé avec linq-to-objets?

Je cherche la solution avec les meilleures performances. P>

Les classes utilisées: P>

List<Animal> animals = new List<Animal>
{
    new Cat(),
    new Dog(),
    new Duck(),
    new MadDuck(),
};

// Get all animals except ducks (and or their derived types)
var a = animals.Where(animal => (animal is Duck == false));
var b = animals.Except((IEnumerable<Animal>)animals.OfType<Duck>());

// Other suggestions
var c = animals.Where(animal => animal.GetType() != typeof(Duck))

// Accepted solution
var d = animals.Where(animal => !(animal is Duck));


8 commentaires

Et si vous avez un madduk , qui hérite d'un canard ? Devrait-il être retourné ou non? Et, BTW, qu'essayez-vous d'atteindre? L'utilisation de est et la vérification de type d'exécution peut indiquer des problèmes de conception.


Bonne question. Dans ce cas particulier, j'aimerais que les sous-classes du canard soient exclues aussi. Cela ferait mon option B invalide alors qu'ils comparent le type mais pas l'héritage.


En ce qui concerne ma deuxième questien: à partir d'un point de vue OOP, d'autres parties de votre code ne doivent généralement pas être concernées par des types réels de vos objets. Le devrait savoir "le moins possible". C'est pourquoi je me demande pourquoi tu fais ça.


@Groo Il y a en effet un problème de conception dans le code fourni les données. Par conséquent, je dois supprimer des classes dérivées spécifiques pour «nettoyer» les données fournies.


@Marceljackwerth Bonne question. Je cherche la solution la mieux performante. J'ai édité la question à inclure cela.


@Aphelion: La vraie question est, puisque vous avez tous le code, à l'exception du chronomètre , pourquoi vous avez demandé cela plutôt que de simplement comprendre les résultats de performance par vous-même.


@ Will Point pris. Merci. Maintenant que j'ai une liste d'options, le chronomètre est en effet la prochaine étape à suivre. En fait, j'ai mis à jour la question avec des suggestions supplémentaires que j'ai proventées des réponses de ma question initiale. A cette époque, je n'avais que 2 options suggérées. J'ai mis à jour la question pour les futures recherches (par d'autres utilisateurs) afin de pouvoir trouver l'option suggérée et la meilleure dans une liste simple.


@Aphelion: gotcha. Je ne sais pas si ça vaut le coup. En règle générale, une personne ayant une question similaire rechercherait et trouverait la vôtre, puis lisez les réponses. Donc, il n'y a pas beaucoup de besoin de modifier la question avec des détails des réponses ...


4 Réponses :


4
votes
  • solution utilisant sauf () est assez lourd.
  • Gardez à l'esprit que la solution est - retournerait vrai même certains Someduck Classe héritée de Duck XXX

    Une autre solution pourrait être: xxx


1 commentaires

Merci. J'ai inclus votre suggestion dans la question.



9
votes

Si vous souhaitez exclure également les sous-classes de canard, le est est le meilleur. Vous pouvez raccourcir le code à juste . Où (animal =>! (Animal est canard));

Sinon, la recommandation de GetType de SLL est la meilleure


2 commentaires

Comme je souhaite exclure les sous-classes et que ceci est une notation plus courte et plus lisible, j'ai accepté votre réponse.


Je ne crois pas que ce battype ().



2
votes

Si vous ne voulez pas canard code> ni aucune sous-classe de Duck code> Pour être retourné, vous devez utiliser la méthode isAssignAdFrom code>:

animals.Where(animal => !animal.GetType().IsAssignableFrom(typeof(Duck)));


2 commentaires

Joli. Je n'ai jamais utilisé IsassignableFrom avant. Je me demande que la performance est pour cette méthode. Cela ressemble à un bon cas pour un profilage.


Je m'attendrais à ce qu'il soit aussi rapide qu'un comme , puis chèque null.



3
votes

Selon () et vérification Tapez où () extension L'appel de l'Oftype est équivalent à votre option (a), bien que est Duck == True , donc basé sur cela, je dirais que je dirais que je dirais que je dirais que je dirais que je dirais que Stick to option (A) .


0 commentaires