IEnumerable
is co-variant but it does not support value type, just only reference type. The below simple code is compiled successfully:
It is perhaps easier to understand if you think about the underlying representation (even though this really is an implementation detail). Here is a collection of strings:
IEnumerable strings = new[] { "A", "B", "C" };
You can think of the strings
as having the following representation:
[0] : string reference -> "A" [1] : string reference -> "B" [2] : string reference -> "C"
It is a collection of three elements, each being a reference to a string. You can cast this to a collection of objects:
IEnumerable
Basically it is the same representation except now the references are object references:
[0] : object reference -> "A" [1] : object reference -> "B" [2] : object reference -> "C"
The representation is the same. The references are just treated differently; you can no longer access the string.Length
property but you can still call object.GetHashCode()
. Compare this to a collection of ints:
IEnumerable ints = new[] { 1, 2, 3 };
[0] : int = 1 [1] : int = 2 [2] : int = 3
To convert this to an IEnumerable
the data has to be converted by boxing the ints:
[0] : object reference -> 1 [1] : object reference -> 2 [2] : object reference -> 3
This conversion requires more than a cast.