単純な継承階層があるとすると、Person-> Student、Teacher、Staff
人物リストLがあるとしましょう。そのリストには、生徒、教師、スタッフが含まれています。
LINQとC#を使用して、特定の種類の人物のみを取得できるメソッドを作成する方法はありますか?
私は次のようなことができることを知っています:
var peopleIWant = L.OfType< Teacher >();
でももっとダイナミックなことができるようになりたいです。考えられるすべてのタイプのPersonの結果を取得するメソッドを作成します。可能なタイプごとにメソッドを作成する必要はありません。
あなたはこれを行うことができます:
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>();
編集:where制約を追加しました。
これでうまくいくはずです。
var students = persons.Where(p => p.GetType() == typeof(Student));
あなたはこれを行うことができます:
IEnumerable<Person> GetPeopleOfType<T>(IEnumerable<Person> list)
where T : Person
{
return list.Where(p => p.GetType() == typeof(T));
}
しかし、実際に行ったことは、LINQのOfType()メソッドを、静的型チェックを使用してPersonを確実に渡す安全なバージョンに書き換えることです。 (リフレクションを使用しない限り)このメソッドを実行時に決定される型で使用することはできません。
そのためには、ジェネリックスを使用するのではなく、型変数をパラメーターにする必要があります。
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);
}
これで、いくつかの型を動的に構築し、それを使用してこのメソッドを呼び出すことができます。
一般的なリストについては、delegate
を使用します。
public List<T> FilterByType(List<T> items, Type filterType)
{
return items.FindAll(delegate(T t)
{
return t.GetType() == filterType;
});
}