Generic Variance in C# 4.0 has been implemented in such a way that it's possible to write the following without an exception (which is what would happen in C# 3.0):
List<int> intList = new List<int>();
List<object> objectList = intList;
[Example non-functional: See Jon Skeet's answer]
I recently attended a conference where Jon Skeet gave an excellent overview of Generic Variance, but I'm not sure I'm completely getting it - I understand the significance of the in
and out
key words when it comes to contra and co-variance, but I'm curious to what happens behind the scenes.
What does the CLR see when this code is executed? Is it implicitly converting the List<int>
to List<object>
or is it simply built in that we can now convert between derived types to parent types?
Out of interest, why wasn't this introduced in previous versions and what's the main benefit - ie real world usage?
More info on this post for Generic Variance (but question is extremely outdated, looking for real, up-to-date information)
No, your example wouldn't work for three reasons:
List<T>
) are invariant; only delegates and interfaces are variantIEnumerable<int>
to IEnumerable<object>
for example(The code fails to compile in both C# 3.0 and 4.0 - there's no exception.)
So this would work:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
The CLR just uses the reference, unchanged - no new objects are created. So if you called objects.GetType()
you'd still get List<string>
.
I believe it wasn't introduced earlier because the language designers still had to work out the details of how to expose it - it's been in the CLR since v2.
The benefits are the same as other times where you want to be able to use one type as another. To use the same example I used last Saturday, if you've got something implements IComparer<Shape>
to compare shapes by area, it's crazy that you can't use that to sort a List<Circle>
- if it can compare any two shapes, it can certainly compare any two circles. As of C# 4, there'd be a contravariant conversion from IComparer<Shape>
to IComparer<Circle>
so you could call circles.Sort(areaComparer)
.
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