为什么'ref'和'out'不支持多态性? [英] Why doesn't 'ref' and 'out' support polymorphism?

查看:24
本文介绍了为什么'ref'和'out'不支持多态性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

采取以下措施:

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

为什么会出现上述编译时错误?refout 参数都会发生这种情况.

Why does the above compile-time error occur? This happens with both ref and out arguments.

推荐答案

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

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

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

UPDATE: I used this answer as the basis for this blog entry:

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

有关此问题的更多评论,请参阅博客页面.谢谢你的好问题.

See the blog page for more commentary on this issue. Thanks for the great question.

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

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

假设你有类 AnimalMammalReptileGiraffeTurtleTiger,具有明显的子类关系.

Let's suppose you have classes Animal, Mammal, Reptile, Giraffe, Turtle and Tiger, with the obvious subclassing relationships.

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

Now suppose you have a method void M(ref Mammal m). M can both read and write m.

你能把 Animal 类型的变量传递给 M 吗?

Can you pass a variable of type Animal to M?

没有.该变量可能包含 Turtle,但 M 将假定它仅包含哺乳动物.乌龟不是哺乳动物.

No. That variable could contain a Turtle, but M will assume that it contains only Mammals. A Turtle is not a Mammal.

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

Conclusion 1: ref parameters cannot be made "bigger". (There are more animals than mammals, so the variable is getting "bigger" because it can contain more things.)

你能把 Giraffe 类型的变量传递给 M 吗?

Can you pass a variable of type Giraffe to M?

没有.M 可以写入 m,而 M 可能想要将 Tiger 写入 m.现在您已将 Tiger 放入一个实际上是 Giraffe 类型的变量中.

No. M can write to m, and M might want to write a Tiger into m. Now you've put a Tiger into a variable which is actually of type Giraffe.

结论2:ref参数不能变小".

现在考虑 N(out Mammal n).

你能把 Giraffe 类型的变量传递给 N 吗?

Can you pass a variable of type Giraffe to N?

没有.N 可以写入 n,而 N 可能想要写入 Tiger.

No. N can write to n, and N might want to write a Tiger.

结论3:out参数不能变小".

你能把 Animal 类型的变量传递给 N 吗?

Can you pass a variable of type Animal to N?

嗯.

好吧,为什么不呢?N 不能从 n 中读取,它只能写入它,对吧?你写一个 Tiger 到一个 Animal 类型的变量,你就准备好了,对吧?

Well, why not? N cannot read from n, it can only write to it, right? You write a Tiger to a variable of type Animal and you're all set, right?

错了.规则不是N 只能写入 n".

Wrong. The rule is not "N can only write to n".

简单来说,规则是:

1) N 必须在N 正常返回之前写入n.(如果 N 抛出,所有赌注都关闭.)

1) N has to write to n before N returns normally. (If N throws, all bets are off.)

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

2) N has to write something to n before it reads something from n.

这允许这样的事件序列:

That permits this sequence of events:

  • 声明 Animal 类型的字段 x.
  • x 作为 out 参数传递给 N.
  • NTiger 写入 n,它是 x 的别名.
  • 在另一个线程上,有人将 Turtle 写入 x.
  • N 尝试读取 n 的内容,并在它认为是 Mammal 类型的变量中发现了一个 Turtle.
  • Declare a field x of type Animal.
  • Pass x as an out parameter to N.
  • N writes a Tiger into n, which is an alias for x.
  • On another thread, someone writes a Turtle into x.
  • N attempts to read the contents of n, and discovers a Turtle in what it thinks is a variable of type Mammal.

显然我们想让它成为非法的.

Clearly we want to make that illegal.

结论4:out参数不能变大".

最终结论:refout 参数都不能改变它们的类型.否则会破坏可验证的类型安全性.

Final conclusion: Neither ref nor out parameters may vary their types. To do otherwise is to break verifiable type safety.

如果您对基本类型理论中的这些问题感兴趣,请考虑阅读 我关于协变和逆变如何在 C# 4.0 中工作的系列文章.

If these issues in basic type theory interest you, consider reading my series on how covariance and contravariance work in C# 4.0.

这篇关于为什么'ref'和'out'不支持多态性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆