I’m targeting .NET 3.5. Let’s say I have a class, Bob, which is an abstract base class for SubBob.
I can declare this:
Bob b = new SubBob();
But I can’t do this:
// compliation error - can't convert
BindingList<Bob> myList = new BindingList<SubBob>();
My guess is that BindingList doesn’t want you to do this because it has to know that the type that’s on the right hand side has the same memory layout as the left hand side. SubBob may have a larger size than a Bob.
Is there a way I can do the implicit conversion, or is a cast required?
The Short Answer
By instantiating
BindingList<SubBob>you confine it to work withSubBoband more specific types (e.g.SubSubBob).If you want
Bobto fit there as well, declaremyListas a list of the least specific type you want to support:(or, more conveniently,)
Explanation
It is not about memory (
BindingListwould only hold a reference to the object, and all references are of the same size), rather it is about logical inconsistency you would introduce.If such code was possible, you would be able to arbitrarily break type restrictions:
myListis a list ofCats, how would you expect it to handle aDog?Compiler wouldn’t know there is a problem and would happily compile your code. What should happen when this code runs? An exception? But generics were introduced exactly to solve type safety problem.
A Side-Note on Co- and Contravariance
It’s correct that in .NET 4.0, generic covariance and contravariance were added for delegates and interfaces (not for classes). For example,
IEnumerable<out T>is covariant that means you can assign it to variable of any type less derived thanT:But this is only possible because
IEnumerable<out T>guarantees it only returnsT(keywordout) and never accepts it. If it acceptedTas parameter, it would open the door to the problem described above. For this reason,ICollectionis not covariant.In a similar fashion, some interfaces guarantee they only accept
T(keywordin) and never return it. Such interfaces are called contravariant and allow assignment to a variable with more specificT: