While Kobi gives a perfect answer how you can get it to work, I will give you a simple answer why it does not work.
In your example, you want to use polymorphism to manage different types that derive from a common base class in a single list of type base class. Something along the lines→
public abstract class Base {}
public class DerivedFirst : Base {}
public class DerivedSecond : Base {}
var first = new DerivedFirst();
var second = new DerivedSecond();
var list = new List<Base>{first,second}
Which is perfectly fine as they derive from the common Base
class. Now let us take a look at your case. But before that you should understand the difference between an Open Type
and Closed Type
. Simply put any generic type without its type parameters are open types and can not be instantiated. List<>
is an open type
whereas List<int>
is a closed type
. When you create a closed type
it does not derive from its open definition. It is a completely new type on its own.
var i_am_false = typeof(List<int>).IsSubclassOf(typeof(List<>));//this is false
Here is your case. You define your classes which will be type arguments.
public abstract class Content
public class ContentA : Content
public class ContentB : Content
Here you define your sources
public abstract class ContentSource<T> where T : Content
public class SourceX : ContentSource<ContentA>
public class SourceY : ContentSource<ContentB>
Putting to words
You have SourceX
which derives from ContentSource<ContentA>
which derives from Object
You have SourceY
which derives from ContentSource<ContentB>
which derives from Object
and finally
You have var ContentSources = new List<ContentSource<Content>>
, which is a list of ContentSource<Content>
which is in no way connected to ContentSource<ContentA>
or ContentSource<ContentB>
. They simply have same implementation with respect to generic parameter.
In the end, let us call
ContentSource<Content>
class M
which derives from Object
ContentSource<ContentA>
class N
which derives from Object
ContentSource<ContentB>
class O
which derives from Object
and have a look at you are doing→
public class SourceX : N{}
public class SourceY : O{}
var ContentSources = new List<M>{
new SourceX(),
new SourceY(),
};
Of course it would not work :).
Lastly why it works with covariance please have a look at Kobi's answer.