简体   繁体   中英

How to filter items from collection based on type stored in variable

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;
}
using System.Linq;

int AnimalsOfType(Type animalType)
{
    return animals.Where(a => a.GetType() == animalType).Count(); ;
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM