Myrtle
Myrtle

Reputation: 5841

Exclude types form IEnumerable with linq

How can I filter out objects based on their derived type with linq-to-objects?

I am looking for the solution with the best performance.

The classes used:

abstract class Animal { }
class Dog : Animal { }
class Cat : Animal { }
class Duck : Animal { }
class MadDuck : Duck { }

I know of three methods: Use the is keyword, use the Except method, and to use the OfType method.

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));

Upvotes: 9

Views: 2891

Answers (4)

Hans Jonus
Hans Jonus

Reputation: 385

According to Difference between OfType<>() and checking type in Where() extension the OfType call is equivalent to your option (a), albeit with is Duck==true, so based on that I would say stick to option (a).

Upvotes: 3

Louis Kottmann
Louis Kottmann

Reputation: 16648

If you don't want Duck nor any subclass of Duck to be returned, you need to use the IsAssignableFrom method:

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

Upvotes: 2

Robert Levy
Robert Levy

Reputation: 29083

If you want to also exclude subclasses of Duck, then the is is best. You can shorten the code to just .Where(animal => !(animal is Duck));

Otherwise, sll's recommendation of GetType is best

Upvotes: 9

sll
sll

Reputation: 62544

  • Solution using Except() is quite heavy.
  • Keep in mind that solution is - would return true even some SomeDuck class inherited from Duck

    class SomeDuck : Duck
    ...
    // duck is Duck == true
    var duck = new SomeDuck();
    

An other solution could be:

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

Upvotes: 4

Related Questions