如何根据存储在变量中的类型从集合中过滤项目
How to filter items from collection based on type stored in variable
我有以下层次结构:
class Animal
class Dog : Animal
class Cat : Animal
我有一个 List<Animal>
集合,想创建一个方法来 return 所有猫或所有狗。但是我不知道如何根据类型变量过滤列表元素。所以像这样:
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.Count(a => a.GetType() == animalType);
}
此处最有效的方法是使用 MakeGenericMethod
和 CreateDelegate
创建泛型方法的委托。您可以将这些委托缓存在字典中
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);
}
第一次调用此方法时,每种类型的启动成本很小。
我有以下层次结构:
class Animal
class Dog : Animal
class Cat : Animal
我有一个 List<Animal>
集合,想创建一个方法来 return 所有猫或所有狗。但是我不知道如何根据类型变量过滤列表元素。所以像这样:
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.Count(a => a.GetType() == animalType);
}
此处最有效的方法是使用 MakeGenericMethod
和 CreateDelegate
创建泛型方法的委托。您可以将这些委托缓存在字典中
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);
}
第一次调用此方法时,每种类型的启动成本很小。