Why doesn#39;t #39;ref#39; and #39;out#39; support polymorphism?(为什么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) {}
}
为什么会出现上述编译时错误?ref 和 out 参数都会发生这种情况.
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.
=============
=============
假设你有类 Animal、Mammal、Reptile、Giraffe、Turtle 和 Tiger,具有明显的子类关系.
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
AnimaltoM?
没有.该变量可能包含 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
GiraffetoM?
没有.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
GiraffetoN?
没有.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
AnimaltoN?
嗯.
好吧,为什么不呢?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. N将Tiger写入n,它是x的别名.- 在另一个线程上,有人将
Turtle写入x. N尝试读取n的内容,并在它认为是Mammal 类型的变量中发现了一个Turtle.
- Declare a field
xof typeAnimal. - Pass
xas anoutparameter toN. Nwrites aTigerinton, which is an alias forx.- On another thread, someone writes a
Turtleintox. Nattempts to read the contents ofn, and discovers aTurtlein what it thinks is a variable of typeMammal.
显然我们想让它成为非法的.
Clearly we want to make that illegal.
结论4:out参数不能变大".
最终结论:ref 和out 参数都不能改变它们的类型.否则会破坏可验证的类型安全性.
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'不支持多态性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么'ref'和'out'不支持多态性?
基础教程推荐
- 经典 Asp 中的 ResolveUrl/Url.Content 等效项 2022-01-01
- 从 VS 2017 .NET Core 项目的发布目录中排除文件 2022-01-01
- 首先创建代码,多对多,关联表中的附加字段 2022-01-01
- 将事件 TextChanged 分配给表单中的所有文本框 2022-01-01
- 是否可以在 asp classic 和 asp.net 之间共享会话状态 2022-01-01
- 如何动态获取文本框中datagridview列的总和 2022-01-01
- 在 VS2010 中的 Post Build 事件中将 bin 文件复制到物 2022-01-01
- JSON.NET 中基于属性的类型解析 2022-01-01
- 错误“此流不支持搜索操作"在 C# 中 2022-01-01
- 全局 ASAX - 获取服务器名称 2022-01-01
