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