为什么我们得到具有ref参数的ArrayTypeMismatch
本文关键字:ref 参数 ArrayTypeMismatch 我们 为什么 | 更新日期: 2023-09-27 18:00:05
给定场景:
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 {}
以及ArrayTypeMisMatch的定义:
尝试存储数组中类型错误的元素。
当试图在数组中存储错误类型的元素时,会引发此异常。例如:
A[] invalid = new A[1];
invalid[0] = "";//I can't store a type of string within an array of type of A
这个异常是如何发生的?为什么我们在调用具有ref
参数的方法时要执行存储操作?
ref
时,也会引发异常。不可否认,仅仅阅读异常文本就不清楚这一点,但在您链接到的页面上,它被非常简短地间接提及:
以下Microsoft中间语言(MSIL)指令引发ArrayTypeMismatchException:
ldelema
ldelema
(加载元素地址)是用于创建对数组元素的引用的指令。
至于原因,它可以防止对的每个ref
参数的每个赋值都需要对类型进行运行时检查。
为什么我们在调用方法时要执行存储操作带有ref参数?
提供数组元素作为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的答案可能更正确,因为它解释了抛出的底层运行时机制,但至少这里有一个实际的演示。