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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1184944/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:18:01  来源:igfitidea点击:

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

c#linqtypeofoftype

提问by Hythloth

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 的结果,而不必为每种可能的类型编写一个方法。

采纳答案by Mladen Prajdic

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 约束。

回答by kareem

This should do the trick.

这应该可以解决问题。

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

回答by Richard Berg

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. You still can't use this method with a type that's determined at runtime (unless you use reflection).

但是您真正所做的只是用一个更安全的版本重写 LINQ 的 OfType() 方法,该版本使用静态类型检查来确保您传入一个 Person。您仍然不能将此方法用于在运行时确定的类型(除非您使用反射)。

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.

现在您可以动态构造某种类型并使用它来调用此方法。

回答by Shahar Shokrani

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;
    });
}