I wonder why IEnumerable
can\'t be assigned to a IEnumerable
. After all IEnumerable
is one of the few interfa
Every value type in .net has a corresponding ("boxed") object type. Non-boxed value types are effectively outside the object type hierarchy, but the compiler will perform a widening from the value type to the boxed class type. It would be helpful to have a "class" Boxed<T> which would support a widening conversions to and from T, but which would be a class type. Internally, I think that's what the compiler's doing implicitly, but I don't know any way to do it explicitly. For any particular type like "integer", there would be no difficulty defining a class which would behave as a Boxed<Integer> should, but I don't know any way of doing such a thing in generic fashion.
The simplistic answer is that this is just one of the quirks in the way that variance is implemented in C# and the CLR.
From "Covariance and Contravariance in Generics":
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.
The problem is that object
is a reference type, not a value type. The only reason you can assign an int
to a variable of type object
is boxing.
In order to assign List<int>
to IEnumerable<object>
you'd have to box each element of the list. You can't do that just by assigning the reference to the list and calling it a different type.
Value types aren't LSP-subtypes of object until they're boxed.
Variance doesn't work with value types. At all.
Demonstration that int
is not a proper subtype (subtype in the LSP sense) of object
:
Works:
object x = new object();
lock (x) { ... }
Does not work (substitutability violated):
int y = new int();
lock (y) { ... }
Returns true:
object x = new object();
object a = x;
object b = x;
return ReferenceEquals(a, b);
Returns false (substitutability violated):
int y = new int();
object a = y;
object b = y;
return ReferenceEquals(a, b);
Of course, the topic of the question (interface variance) is a third demonstration.