Given a simple inheritance hierarchy:
Person -> Student, Teacher, Staff
Say I have a list of Persons, L.
In that list are some Students, Teachers, and Staff.
Using LINQ and C#, is there a way I could write a method that could retrieve only a particular type of person?
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.
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.
This should do the trick.
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. 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
:
public List<T> FilterByType(List<T> items, Type filterType)
{
return items.FindAll(delegate(T t)
{
return t.GetType() == filterType;
});
}