4 ms·
If you have a class Sub implementing an interface IBase. How does C# handle the case of List<Sub> being used as List<IBase>? If it is allowed, does it let you
by Peaker 14y ago
If you have a class Sub implementing an interface IBase.
How does C# handle the case of List<Sub> being used as List<IBase>?
If it is allowed, does it let you do:
List<IBase> base = subList;
base.append(someOtherSub); // Oops! Broken invariant
Is List<T> covariant on T? If not, that's a thorny edge case, which results from the combination of OO-subtyping and generics.
- pcwalton 14y agoType parameters are invariant, unless explicitly specified to be covariant with a where clause.
- Peaker 14y agoWell, if List<T> is invariant on the T, then you cannot usefully have lists parameterized on interfaces, which is losing a useful ability. I'd say that classifies as a thorny edge case. In Haskell, I can represent the type: (Show a, Ord a) => [a] It seems like the same is impossible in C# due to generics' interaction with inheritance.
- Someone 14y agoIn C#, generic classes cannot be co- or contravariant on their types, but interfaces can. IList<T> itself is not covariant, as that would open the hole you mention, but it extends interface of IEnumerable<T>, which is covariant (it only allows you take T's out of the List, so it is OK if you do var subs = new List<Sub>(); ... IEnumerable<Base> bases = subs; The objects that 'subs' produces are guaranteed to be Sub's, and hence Base's, and you cannot insert a Base into 'subs' this way because IEnumerable does not have a method for doing that. More info at http://msdn.microsoft.com/en-us/library/dd799517.aspx http://msdn.microsoft.com/en-us/library/dd799517.aspx.