为了账号安全,请及时绑定邮箱和手机立即绑定

为什么“ ref”和“ out”不支持多态?

为什么“ ref”和“ out”不支持多态?

C#
米脂 2019-10-08 09:46:21
采取以下措施:class A {}class B : A {}class C{    C()    {        var b = new B();        Foo(b);        Foo2(ref b); // <= compile-time error:                      // "The 'ref' argument doesn't match the parameter type"    }    void Foo(A a) {}    void Foo2(ref A a) {}  }为什么会出现上述编译时错误?ref和out参数都会发生这种情况。
查看完整描述

3 回答

?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

=============


更新:我使用此答案作为此博客条目的基础:


为什么ref和out参数不允许类型变化?


有关此问题的更多评论,请参见博客页面。感谢您提出的重大问题。


=============


让我们假设你有课Animal,Mammal,Reptile,Giraffe,Turtle和Tiger,具有明显的子类关系。


现在假设您有一个方法void M(ref Mammal m)。  M可以读写m。


您可以将类型的变量传递Animal给M吗?


否。该变量可以包含Turtle,但M将假定它仅包含哺乳动物。A Turtle不是Mammal。


结论1:ref不能使参数“更大”。(动物比哺乳动物多,因此该变量变得“更大”,因为它可以包含更多的东西。)


您可以将类型的变量传递Giraffe给M吗?


号M可以写入m,并且M可能要编写一个Tiger成m。现在,您已将a Tiger放入实际类型为的变量中Giraffe。


结论2:ref不能使参数“更小”。


现在考虑N(out Mammal n)。


您可以将类型的变量传递Giraffe给N吗?


号N可以写n,并且N可能要写一个Tiger。


结论3:out不能使参数“更小”。


您可以将类型的变量传递Animal给N吗?



好吧,为什么不呢?  N无法读取n,只能写入,对不对?您将a写入Tiger类型的变量,Animal就已经准备好了,对吧?


错误。规则不是“ N只能写n”。


这些规则是:


1)在正常返回之前N必须先写入。(如果抛出,则所有投注均无效。)nNN


2)N必须先写入内容,n然后才能从中读取内容n。


这允许发生以下一系列事件:


声明一个xtype 字段Animal。

x作为out参数传递给N。

N写入一个,Tiger到n的别名x。

在另一个线程,有人写了一Turtle成x。

N试图阅读的内容n,并发现Turtle它认为是类型的变量Mammal。

显然,我们想使之非法。


结论4:out不能将参数设为“更大”。


最后得出结论:无论是ref也不out参数可能有所不同它们的类型。否则将破坏可验证的类型安全性。


如果您对基本类型理论中的这些问题感兴趣,请考虑阅读我的有关协方差和反方差如何在C#4.0中工作的系列。


查看完整回答
反对 回复 2019-10-08
?
www说

TA贡献1775条经验 获得超8个赞

因为在两种情况下,您都必须能够将值分配给ref / out参数。


如果您尝试将b传递给Foo2方法作为引用,并且在Foo2中尝试使用a = new A(),则此方法无效。

不能写的原因相同:


B b = new A();


查看完整回答
反对 回复 2019-10-08
  • 3 回答
  • 0 关注
  • 384 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信