Подтвердить что ты не робот

LINQ: из списка типа T извлекают только объекты определенного подкласса S

Учитывая простую иерархию наследования: Лицо → Студент, учитель, персонал

Скажем, у меня есть список людей, Л. В этом списке есть несколько учеников, преподавателей и сотрудников.

Используя LINQ и С#, есть ли способ написать метод, который мог бы получить только определенный тип человека?

Я знаю, что могу сделать что-то вроде:

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

Но я хочу иметь возможность делать что-то более динамичное. Я хотел бы написать метод, который будет извлекать результаты для любого типа Person, о котором я мог думать, без необходимости писать метод для всех возможных типов.

4b9b3361

Ответ 1

вы можете сделать это:

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: добавлено ограничение where.

Ответ 2

Это должно сделать трюк.

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

Ответ 3

Вы можете сделать это:

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

Но все, что вы действительно сделали, - это переписать метод LINQ OfType() с более безопасной версией, которая использует статическую проверку типов, чтобы обеспечить передачу персонажа. Вы все еще не можете использовать этот метод с типом, определенным во время выполнения (если вы не используете отражение).

Для этого вместо использования дженериков вам нужно будет сделать переменную типа параметром:

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

Теперь вы можете построить некоторый тип динамически и использовать его для вызова этого метода.

Ответ 4

Для общего списка используйте delegate:

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