While reading c# in a nutshell about boxing and unboxing on page 91, author writes this:
Boxing conversions are crucial in providing a,unified type system. The system is not perfect, however we will see in Generics that variance with arrays and generics supports only **reference conversions ** and not **boxing conversions **
And quoted example code:
object [] a1 = new string [3]; //legal
object [] a2 = new int [3]; // error
Can somebody explain what the author is trying to deliver and why the first line is legal and second line is not?
Well, there's a reference conversion between string
and object
, in that every string reference can be treated as an object reference. This can be done transparently, with no modification to the value at all. That's why array variance can be done cheaply - for reads, anyway. Reading from an object[]
value (as is known at compile-time) which happens to really be a string[]
at execution time is basically free - you read the value, and you can treat it as an object
reference. Writing is more painful - every write to an object[]
has to check that the value you're writing is genuinely compatible with the array you're trying to store it in.
The important thing here is that the representation of a string
reference is the same as the representation of an object
reference.
There's a boxing conversion between int
and object
which lets this work:
int x = 10;
object y = x;
... but that conversion involves more action; the CLR has to create an object which contains the relevant integer. The representation of an int
is not the same as the representation of an object
reference. Checking whether that's necessary - and doing it as you go - would be relatively painful (from a performance perspective) when reading from an array, so it's not valid to treat an int[]
as an object[]
.
The same is true for generic variance. This is fine:
List<string> strings = new List<string>();
IEnumerable<object> objects = strings; // IEnumerable<T> is covariant in T
But this isn't:
List<int> ints = new List<int>();
IEnumerable<object> objects = ints; // Covariance doesn't apply here
For more on representation and identity, see Eric Lippert's blog post on the topic. (It doesn't talk about variance very much, but it's all related...)
See more on this question at Stackoverflow