Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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));
like image 844
Myrtle Avatar asked Feb 01 '12 14:02

Myrtle


2 Answers

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

like image 66
Robert Levy Avatar answered Oct 17 '22 16:10

Robert Levy


  • 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))
like image 30
sll Avatar answered Oct 17 '22 16:10

sll