Reputation: 44285
Given the scenerio:
public class Program
{
static void Main()
{
object[] covarientArray= new A[] { new A() };
object polymorphism = new A();
object test = covarientArray[0];
M(ref polymorphism);//fine up to here
M(ref covarientArray[0]);//ArrayTypeMismatchException
}
static void M(ref object o) { Console.WriteLine(o); }
}
class A {}
And the definition of ArrayTypeMisMatch:
The exception that is thrown when an attempt is made to store an element of the wrong type within an array.
This Exception is thrown when an attemp is made to store an element of the wrong type within an array. E.G.:
A[] invalid = new A[1];
invalid[0] = "";//I can't store a type of string within an array of type of A
How does this exception occur? Why is it that we are doing a store operation when Invoking a method with a ref
param?
Upvotes: 3
Views: 78
Reputation: 23218
Why is it that we are doing a store operation when Invoking a method with a ref param?
Providing an array element as the argument to a ref
parameter actually is a store operation, at least potentially. (Yeah, you might not reassign it, but the compiler/runtime doesn't necessarily know that)
Imagine if your M
method implementation was this:
static void M(ref object o)
{
o = new B();
}
If we type your covariant array as object[]
to so it compiles and works:
object[] covariantArray= new object[] { new A() };
M(ref covariantArray[0]);
Console.WriteLine(covariantArray[0].GetType().Name); //B
It runs and replaced the first element with a new instance of B. Of course, this is perfectly valid for an object[]
array. So now if we simply change it to A[]
:
object[] covariantArray= new A[] { new A() };
M(ref covariantArray[0]); //ArrayTypeMismatchException
Console.WriteLine(covariantArray[0].GetType().Name);
It throws the exception before the potentially dangerous/catastrophic/dogs-are-cats/up-is-down call to M
is processed.
Of course, remove the ref
calls or ref
against a local variable instead of the array element and it works perfectly fine since you're not messing around with the array contents.
@hvd's answer is probably more correct in that it explains the underlying runtime mechanism for throwing, but at least here's a practical demonstration why it is so.
Upvotes: 1
Reputation:
The exception is also thrown when creating a ref
to an array element of the wrong type. This is admittedly unclear by just reading the exception text, but it is very briefly mentioned indirectly on the page you linked to:
The following Microsoft intermediate language (MSIL) instructions throw ArrayTypeMismatchException :
ldelema
ldelema
(load element address) is the instruction used to create a reference to an array element.
As for the why, it prevents every assignment to every ref
argument from needing to do a run-time check of the type.
Upvotes: 3