Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么我们会得到与ref参数不匹配的ArrayTypeMismatch?_C# - Fatal编程技术网

C# 为什么我们会得到与ref参数不匹配的ArrayTypeMismatch?

C# 为什么我们会得到与ref参数不匹配的ArrayTypeMismatch?,c#,C#,给定场景: 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(r

给定场景:

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 {}

尝试存储时引发的异常 数组中类型错误的元素

当尝试在数组中存储错误类型的元素时,会引发此异常。例如:

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:

阿尔德勒马

(加载元素地址)是用于创建对数组元素的引用的指令

至于为什么,它防止每个
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实例替换第一个元素。当然,这对于
对象[]
数组是完全有效的。现在,如果我们简单地将其更改为
A[]

object[] covariantArray= new A[] { new A() };
M(ref covariantArray[0]); //ArrayTypeMismatchException
Console.WriteLine(covariantArray[0].GetType().Name);
在处理潜在危险/灾难/狗是猫/向上是向下调用
M
之前,它抛出异常

当然,删除对局部变量而不是数组元素的
ref
调用或
ref
,这样就可以很好地工作,因为您没有弄乱数组内容


@hvd的答案可能更正确,因为它解释了抛出的底层运行时机制,但至少这里有一个实际的演示说明为什么会这样。

我对数组是协变的感到震惊。想象一下如果
M
做了这样的事情:
o=new B()
;突然间,您的
covarientArray
实际上是
a[]
,现在它的第一个元素中包含了
B
的一个实例!编辑:为了回答您的问题,在传递数组元素时执行
ref
可以完全替换该元素:这是一个存储操作,至少可能是这样。@KendallFrey You和我。这与C#的伟大之处背道而驰。Eric Lippert有一篇关于它的帖子以及它被收录的原因:也许如果C#4.0中的协方差加法在C#1.0时代就已经存在,那就不同了。是的,这就是我回答的最后一句话的意思,
o=new B()需要在运行时检查
o
是否真的允许存储
B
。你的答案清楚多了。@hvd-两个答案都有重要信息。太糟糕了,我不能选择2。@hvd+1问题:这只是为了避免检查每个作业而进行的“优化”步骤吗?如中所示,如果您有
o=newa()方法中的十次,它只检查一次而不是十次?然后,如果没有“优化”,您可以传递一个
ref
,而无需指定一个值,该值应使调用
M
“ok”,对吗?但是,如果运行时允许执行该方法,用户反而会在
o=new B()
行上得到异常,从本地上下文来看,抛出异常似乎是一个非常非常非常奇怪/糟糕的地方。对我来说,“优化”意味着它不应该改变行为,但如果允许的话,这显然是可能的。@ChrisSinclair我不确定我是否理解你的问题。从实现的角度来看,我不会将其归类为优化,因为所有实现都需要抛出异常。根据CLR规范作者的观点,我将其归类为优化,因为规范可能会说检查会在以后进行。