I just don't get something in the .NET generic type casting. Can someone explain what happens in the following code snippet?
void Main()
{
IEnumerable<int> ints = new List<int>();
IEnumerable<string> strings = new List<string>();
var rez1=(IEnumerable<object>)ints; //runtime error
var rez2=(IEnumerable<object>)strings; //works
var rez3=(List<object>)strings; //runtime error
}
Let's start with the second line which is easiest.
That cast works because the type parameter of IEnumerable<T>
is now covariant (that's what the out
in out T
does). This means you can cast an IEnumerable<Derived>
to an IEnumerable<Base>
freely.
The first line, which would seem to be the same case, does not work because int
is a value type. Interface variance does not work with value types at all because value types do not really inherit from System.Object
; they can be boxed into an object
, but that's not the same. The documentation mentions that
Variance applies only to reference types; if you specify a value type for a variant type parameter, that type parameter is invariant for the resulting constructed type.
Finally, the third line does not work because the type parameter of List<T>
is invariant. You can see there is no out
on its type parameter; the rules disallow that because List<T>
is not an interface:
In the .NET Framework 4, variant type parameters are restricted to generic interface and generic delegate types.
This is because interface covariance only works with reference types. Int32, of course, is a value type.
This gives more information: http://blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx
And so does this: http://ericlippert.com/2011/09/19/inheritance-and-representation/
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