Example:
public abstract class Person
{
public void DoSomething(IEnumerable<Person> persons) { }
}
public class Teacher : Person { }
public class Student : Person { }
The question - why won't it work?
Exactly, if I want to call this method with IEnumerable<Student> I'd need to cast it. And not just normally cast, but with the extension method .Cast<Person>()There are several more or less valid reasons for this need, which doesn't change the fact that it's annoying and doesn't serve the purpose of what I want to allow.
A very easy workaround which allows us to do everything we need:
public abstract class Person
{
public void DoSomething<T>(IEnumerable<T> persons) where T : Person { }
}
public class Teacher : Person { }
public class Student : Person { }
Ok, but what if I want my DoSomething of Teacher only be used with Teacher?
public abstract class Person<T> where T : Person
{
public void DoSomething(IEnumerable<T> persons) { }
}
public class Teacher : Person<Teacher> { }
public class Student : Person<Person> { }
And this was only the starter - what if you want to have a List of a List, but don't really care if it's an array, IEnumerable, Collection or an actual List?
public abstract class Person
{
// Limits you to IEnumerable<Person> as inner generic.
// Example IEnumerable<Person>[] or List<IEnumerable<Person>> ...
public void DoSomethingMore(IEnumerable<IEnumerable<Person>>) { }
// No limitations
public void DoSomethingBetter<T>(IEnumerable<T> persons)
where T : IEnumerable<Person> { }
}
public class Teacher : Person<Teacher> { }
public class Student : Person<Person> { }
As you can see you can call DoSomethingBetter any way of combining collections as you want. Even with Person[][] or List<HashSet<Person>>.
Happy Coding!
Peter