Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics type casting

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
}
like image 556
Vasaka Avatar asked Sep 11 '12 17:09

Vasaka


2 Answers

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.

like image 56
Jon Avatar answered Oct 19 '22 06:10

Jon


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/

like image 42
phoog Avatar answered Oct 19 '22 07:10

phoog