鉴于场景:
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 {}
的定义
尝试存储时抛出的异常 数组中错误类型的元素。
当尝试存储数组中错误类型的元素时,抛出此异常。 E.G:
A[] invalid = new A[1];
invalid[0] = "";//I can't store a type of string within an array of type of A
这种异常是如何发生的?为什么在调用带有ref
param的方法时,我们正在进行存储操作?
答案 0 :(得分:3)
在为错误类型的数组元素创建ref
时也会抛出异常。仅仅通过阅读异常文本就可以清楚地看到这一点,但是在您链接到的页面上间接地简要地提到了它:
以下Microsoft中间语言(MSIL)指令抛出ArrayTypeMismatchException:
ldelema
ldelema
(加载元素地址)是用于创建对数组元素的引用的指令。
至于原因,它阻止 每个 ref
参数的每个赋值都需要对类型进行运行时检查。
答案 1 :(得分:1)
为什么在调用方法时我们正在进行存储操作 用ref param?
提供一个数组元素作为ref
参数的参数,实际上 是一个商店操作,至少可能是这样。 (是的,您可能不重新分配它,但编译器/运行时不一定知道那个)
想象一下,如果你的M
方法实现是这样的话:
static void M(ref object o)
{
o = new B();
}
如果我们将您的协变数组键入object[]
,那么它就会编译并运行:
object[] covariantArray= new object[] { new A() };
M(ref covariantArray[0]);
Console.WriteLine(covariantArray[0].GetType().Name); //B
它运行并用新的B 实例替换第一个元素。当然,这对object[]
数组完全有效。现在,如果我们只是将其更改为A[]
:
object[] covariantArray= new A[] { new A() };
M(ref covariantArray[0]); //ArrayTypeMismatchException
Console.WriteLine(covariantArray[0].GetType().Name);
它会在处理M
潜在危险/灾难性/狗 - 猫/上下呼叫之前抛出异常。
当然,针对局部变量而不是数组元素移除ref
调用或ref
,因为您没有弄乱数组内容,所以它可以正常工作。
@ hvd的答案可能更正确,因为它解释了投掷的基本运行时机制,但至少在这里是一个实际的演示为什么会这样。