IEnumerable
is co-variant but it does not support value type, just only reference type. The below simple code is compiled successfully:
It does come down to an implementation detail: Value types are implemented differently to reference types.
If you force value types to be treated as reference types (i.e. box them, e.g. by referring to them via an interface) you can get variance.
The easiest way to see the difference is simply consider an Array
: an array of Value types are put together in memory contiguously (directly), where as an array of Reference types only have the reference (a pointer) contiguously in memory; the objects being pointed to are separately allocated.
The other (related) issue(*) is that (almost) all Reference types have the same representation for variance purposes and much code does not need to know of the difference between types, so co- and contra-variance is possible (and easily implemented -- often just by omission of extra type checking).
(*) It may be seen to be the same issue...