Reputation: 167
If I have a GenericClass
with a type constraint of where T : BaseType
, why can't I pass it as GenericClass<BaseType>
?
class GenericClass<T> where T : BaseType
{
void Method()
{
new UtilityClass().Method(this);
}
}
class UtilityClass
{
internal void Method(GenericClass<BaseType> genericClass)
{
}
}
The static analyser error:
Cannot convert from 'GenericsPoc.GenericClass<T>' to
'GenericsPoc.GenericClass<GenericsPoc.BaseType>'
I didn't expect this since UtilityClass<T>
the T
has to inherit from BaseClass
.
Upvotes: 0
Views: 196
Reputation: 660463
This question is asked every day. One more time!
class Cage<T> where T : Animal
{
public void Add(T t) { ... }
}
Now your question is: why is this illegal?
Cage<Animal> cage = new Cage<Gerbil>();
Because this line is legal:
cage.Add(new Tiger());
Cage<Animal>
has a method Add
which takes Animal
. A Tiger
is an Animal
so that must be legal. But that means that we just put a tiger into a gerbil cage.
Since that line must be legal and it causes a type error, some other line must be illegal, and now you know which one it is.
The feature you want is called generic covariance and it is legal in C# when:
For example:
IEnumerable<Animal> animals = new List<Tiger>() { new Tiger() };
That's legal. List<Tiger>
implements IEnumerable<Tiger>
, which is an interface and marked as safe for covariance, so it can be assigned to IEnumerable<Animal>
.
You'll note that there is no way to put a duck into a sequence of animals, and therefore there is no way to put a duck into a sequence of tigers. That's how we know that it is safe for covariance.
Upvotes: 4
Reputation: 7803
You need to modify UtilityClass
so that the method also passes down the generic type:
internal void Method<T>(GenericClass<T> genericClass) where T: BaseType
{
}
Upvotes: 2