I am trying to use polymorphism in generic type parameters in C#. I have reviewed several other questions on SO (1, 2, 3, 4, 5, 6), but I'm still not clear why this doesn't work (or if it's even allowed).
Background
I have the following classes:
public class Base { }
public class Derived<T> : Base { }
public class Foo { }
and an instance of my derived generic type:
var derived = new Derived<Foo>();
The basics
The following statements are all true:
derived is Object
derived is Base
derived is Derived<Foo>
The problem
When I try to use my derived class as a type parameter in another generic type I get some unexpected behavior. Given the following lazy instance:
var lazy = new Lazy<Derived<Foo>>();
The following is true:
lazy is Lazy<Derived<Foo>>
But these are false when I expected them to be true:
lazy is Lazy<Object>
lazy is Lazy<Base>
Why is this? Should they be true or have I misunderstood how generics work?
Whatever<Something>
isn't the same type as aWhatever<object>
. – Impedimentderived is Derived<Foo>
is true butderived is Derived<Object>
is false. The same applies to lazy too. – McgannonSomething
orFoo
are bothObject
s. Can they not be substituted forObject
in the type parameter? – Visigothobject
but they are notWhatever<object>
– ImpedimentList<String>
andList<object>
. While it is true that anything that can be stored in the first can also be stored in the last, they are still considered very different things, stored in different ways. Putting a string in aList<object>
and then retrieving it will return a value of typeobject
, notString
. The generic type is not the defining trait of the type. It is "a list of strings", rather than "a list of strings". It sounds pedantic, but there is a notable difference to consider. – Gonococcus