Say I have a setup like
public interface IMyInterface { }
public class MyImplementation : IMyInterface { }
public class MyClass<T> where T : IMyInterface { }
I figured out that I can't do a substitution like
var list = new List<MyClass<IMyInterface>>()
{
new MyClass<MyImplementation>()
}
as I'll get the error
Cannot convert from
MyClass<MyImplementation>
toMyClass<IMyInterface>
Does that mean what I'm trying to do is code smell?
It does not allow that because the
T
inList<T>
is invariant. Here is an example which will explain:Let's add some fruits to a list:
Later in the code, you have no idea what was added and you do this:
Now that will not compile but it also does not make sense because every
IFruit
is not anApple
or anOrange
.What if the compiler allowed it?
If, for instance let's say, what you are trying was allowed by the compiler, like this:
Then if the compiler allowed that, it should also allow this since they both implement
IFruit
:then later on somewhere in code you do this (since it is a list of apples):
Crash!! The compiler did not stop you at the beginning and at this point you are looking at the code and it says
List<Apple>
, and you wrote code and all compiled. At runtime, oh crap, there is noColor
property because it is anOrange
.This is why it is not allowed.