Why are we getting ArrayTypeMismatch with ref parameters?
Given 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 trying to store an element of the wrong type inside an array.
This exception is thrown when an attemp is created to store an element of the wrong type in an array. For example:.
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 happen? Why are we doing a store operation when calling a method with a parameter ref
?
source to share
Why are we doing a store operation when calling a method? with a ref parameter?
Providing an array element as a parameter argument is ref
actually a store operation, at least potentially. (Yes, you can't reassign it, but the compiler / runtime doesn't necessarily know this)
Imagine the implementation of the method M
is as follows:
static void M(ref object o)
{
o = new B();
}
If we type your covariant array like object[]
this so that it compiles and works:
object[] covariantArray= new object[] { new A() };
M(ref covariantArray[0]);
Console.WriteLine(covariantArray[0].GetType().Name); //B
It starts and replaces the first element with a new instance of B. Of course this works great for an array object[]
. So now if we just change it to A[]
:
object[] covariantArray= new A[] { new A() };
M(ref covariantArray[0]); //ArrayTypeMismatchException
Console.WriteLine(covariantArray[0].GetType().Name);
It will throw an exception before a potentially dangerous / catastrophic / dog-cat / up-down call is processed M
.
Of course, remove the calls to ref
or ref
for the local variable instead of the array element and it works great since you don't mess with the contents of the array.
@hvd's answer is probably more correct as it explains the basic execution mechanism for throwing, but at least here's a practical demonstration of why that is.
source to share
An exception is also thrown when ref
the wrong array type is created for an element. This is admittedly unclear just by reading the text of the exception, but it is mentioned very briefly on the page you linked to:
The following Microsoft Intermediate Language (MSIL) statements throw an ArrayTypeMismatchException:
ldelema
ldelema
(load item address) is an instruction used to create a reference to an array item.
How and why, it prevents every assignment to every argument ref
from having to do a runtime check.
source to share