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