I have the following hierarchy:
class Animal
class Dog : Animal
class Cat : Animal
I have a List<Animal>
collection and want to make a method that will return all cats or all dogs. However I can't figure out how to filter the list elements based on a type variable. So like this:
int AnimalsOfType(Type animalType)
{
// Gives error "animalType is a variable but is used like a type".
return animals.OfType<animalType>().Count;
}
CodePudding user response:
using System.Linq;
int AnimalsOfType(Type animalType)
{
return animals.Count(a => a.GetType() == animalType);
}
CodePudding user response:
The most efficient method here is to use MakeGenericMethod
and CreateDelegate
to create delegates to generic methods. You can cache these delegates in a dictionary
static Dictionary<Type, Func<List<Animal>, int>> _methods = new Dictionary<Type, Func<List<Animal>, int>>();
static int CountOfType<T>(List<Animal> source) =>
source.Count(a => a is T);
int AnimalsOfType(List<Animal> animals, Type animalType)
{
if(!_methods.TryGetValue(animalType, out var dlgt))
{
dlgt = (Func<List<Animal>, int>)
this.GetType().GetMethod("CountOfType")
.MakeGenericMethod(animalType)
.CreateDelegate(typeof(Func<List<Animal>, int>)));
_methods[animalType] = dlgt;
}
return dlgt(animals);
}
There is a single small startup cost the first time you call this method, per type.