简体   繁体   English

LINQ:从类型 T 的列表中,仅检索某个子类 S 的对象

[英]LINQ: From a list of type T, retrieve only objects of a certain subclass S

Given a simple inheritance hierarchy: Person -> Student, Teacher, Staff给定一个简单的继承层次结构:Person -> Student、Teacher、Staff

Say I have a list of Persons, L. In that list are some Students, Teachers, and Staff.假设我有一个 Person 列表,L。在该列表中是一些学生、教师和工作人员。

Using LINQ and C#, is there a way I could write a method that could retrieve only a particular type of person?使用 LINQ 和 C#,有没有一种方法可以编写一种只能检索特定类型人的方法?

I know I can do something like:我知道我可以这样做:

var peopleIWant = L.OfType< Teacher >();

But I want to be able to do something more dynamic.但我希望能够做一些更有活力的事情。 I would like to write a method that will retrieve results for any type of Person I could think of, without having to write a method for every possible type.我想编写一个方法来检索我能想到的任何类型的 Person 的结果,而不必为每种可能的类型编写一个方法。

you can do this:你可以这样做:

IList<Person> persons = new List<Person>();

public IList<T> GetPersons<T>() where T : Person
{
    return persons.OfType<T>().ToList();
}

IList<Student> students = GetPersons<Student>();
IList<Teacher> teacher = GetPersons<Teacher>();

EDIT: added the where constraint.编辑:添加了 where 约束。

这应该可以解决问题。

var students = persons.Where(p => p.GetType() == typeof(Student));

You could do this:你可以这样做:

IEnumerable<Person> GetPeopleOfType<T>(IEnumerable<Person> list)
    where T : Person
{
    return list.Where(p => p.GetType() == typeof(T));
}

But all you've really done is rewrite LINQ's OfType() method with a safer version that uses static type checking to ensure you pass in a Person.但是您真正所做的只是用一个更安全的版本重写 LINQ 的 OfType() 方法,该版本使用静态类型检查来确保您传入一个 Person。 You still can't use this method with a type that's determined at runtime (unless you use reflection).您仍然不能将此方法用于在运行时确定的类型(除非您使用反射)。

For that, rather than using generics, you'll have to make the type variable a parameter:为此,您必须将类型变量设为参数,而不是使用泛型:

IEnumerable<Person> GetPeopleOfType(IEnumerable<Person> list, Type type)
{
    if (!typeof(Person).IsAssignableFrom(type))
        throw new ArgumentException("Parameter 'type' is not a Person");

    return list.Where(p => p.GetType() == type);
}

Now you can construct some type dynamically and use it to call this method.现在您可以动态构造某种类型并使用它来调用此方法。

For general list, using delegate :对于一般列表,使用delegate

public List<T> FilterByType(List<T> items, Type filterType)
{
    return items.FindAll(delegate(T t)
    {
        return t.GetType() == filterType;
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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