The reason this code works is due to the fact that the Enumerator
cannot modify the collection:
var roList = new List<string>() { "One", "Two", "Three" };
IEnumerable<object> objEnum = roList;
If we try to do the same thing with a List<object>
, instead of IEnumerable<object>
, we would get a compiler error telling us that we cannot implicitly convert type List<string>
to List<object>
. Alright, that one makes sense and it was a good decision by Microsoft, in my opinion, as a lesson learned from arrays.
However, what I can't figure out is why in the world is this hardline rule applicable to something like ReadOnlyCollection
? We won't be able to modify the elements in the ReadOnlyCollection
, so what is the safety concern that caused Microsoft to prevent us from using covariance with something that's read-only? Is there a possible way of modifying that type of collection that Microsoft was trying to account for, such as through pointers?
Variance and contravariance only work on interfaces and delegates, not on classes.
However, you can do that (using .NET 4.5):
ReadOnlyCollection<string> roList = ...
IReadOnlyCollection<object> objects = roList;
(because IReadOnlyCollection<T>
is covariant)
To answer your question about why variance isn't allowed on classes, here's Jon Skeet's explanation from his C# in Depth book (second edition, §13.3.5, page 394).
NO VARIANCE FOR TYPE PARAMETERS IN CLASSES
Only interfaces and delegates can have variant type parameters. Even if you have a class that only uses the type parameter for input (or only uses it for output), you can’t specify the
in
orout
modifiers. For exampleComparer<T>
, the common implementation ofIComparer<T>
, is invariant — there’s no conversion fromComparer<IShape>
toComparer<Circle>
.Aside from any implementation difficulties that this might’ve incurred, I’d say it makes a certain amount of sense conceptually. Interfaces represent a way of looking at an object from a particular perspective, whereas classes are more rooted in the object’s actual type. This argument is weakened somewhat by inheritance letting you treat an object as an instance of any of the classes in it s inheritance hierarchy, admittedly. Either way, the CLR doesn’t allow it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With