[英]Why do we get ArrayTypeMismatch with ref params?
Given the scenerio: 鉴于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: 而且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. 当尝试在数组中存储错误类型的元素时,抛出此异常。 EG:
例如:
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? 为什么在使用
ref
param调用方法时我们正在进行存储操作?
The exception is also thrown when creating a ref
to an array element of the wrong type. 在为错误类型的数组元素创建
ref
时,也会抛出异常。 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 :
以下Microsoft中间语言(MSIL)指令抛出ArrayTypeMismatchException:
ldelema
ldelema
ldelema
(load element address) is the instruction used to create a reference to an array element. ldelema
(load element address)是用于创建对数组元素的引用的指令。
As for the why, it prevents every assignment to every ref
argument from needing to do a run-time check of the type. 至于原因,它阻止每个
ref
参数的每个赋值都需要对类型进行运行时检查。
Why is it that we are doing a store operation when Invoking a method with a ref param?
为什么在使用ref param调用方法时我们正在进行存储操作?
Providing an array element as the argument to a ref
parameter actually is a store operation, at least potentially. 提供数组元素作为
ref
参数的参数实际上是存储操作,至少是潜在的。 (Yeah, you might not reassign it, but the compiler/runtime doesn't necessarily know that) (是的,您可能不会重新分配它,但编译器/运行时不一定知道 )
Imagine if your M
method implementation was this: 想象一下,如果你的
M
方法实现是这样的:
static void M(ref object o)
{
o = new B();
}
If we type your covariant array as object[]
to so it compiles and works: 如果我们将你的协变数组类型设置为
object[]
,那么它将编译并运行:
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 . 它运行并用 新的B实例 替换第一个元素。 Of course, this is perfectly valid for an
object[]
array. 当然,这对于
object[]
数组是完全有效的。 So now if we simply change it to A[]
: 所以现在我们只需将其改为
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. 它会在处理潜在危险/灾难性/狗是猫/向上呼叫
M
之前抛出异常。
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. 当然,删除
ref
调用或ref
局部变量而不是数组元素,它完全正常,因为你没有搞乱数组内容。
@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. @ hvd的答案可能更正确,因为它解释了投掷的底层运行时机制,但至少在这里是一个实际的演示为什么会如此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.