为什么不'裁判'和'去'的支持多态? [英] Why doesn't 'ref' and 'out' support polymorphism?
问题描述
看看下面的:
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
和退出
参数。
推荐答案
=============
=============
更新:我用这个答案作为此博客条目的基础:
UPDATE: I used this answer as the basis for this blog entry:
<一个href=\"http://blogs.msdn.com/ericlippert/archive/2009/09/21/why-do-ref-and-out-parameters-not-allow-type-variation.aspx\">Why做ref和out参数不允许类型变化?
有关此问题的详细解说,请参阅博客页面。感谢伟大的问题。
See the blog page for more commentary on this issue. Thanks for the great question.
=============
=============
让我们假设你有类动物
,哺乳动物
,爬虫
,长颈鹿
,龟
和虎
,用显而易见子类之间的关系。
Let's suppose you have classes Animal
, Mammal
, Reptile
, Giraffe
, Turtle
and Tiger
, with the obvious subclassing relationships.
现在假设你有一个方法无效M(REF哺乳动物M)
。 M
可以同时读取和写入 M
。
Now suppose you have a method void M(ref Mammal m)
. M
can both read and write m
.
您可以通过键入动物
的变量 M
?
Can you pass a variable of type
Animal
toM
?
没有。该变量可能包含一个龟
,但 M
将假设它只包含哺乳动物。 A 龟
不是哺乳动物
。
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.)
您可以通过键入长颈鹿
的变量 M
?
Can you pass a variable of type
Giraffe
toM
?
没有。 M
可写入 M
和 M
可能要写了虎
到 M
。现在,你已经把一个虎
成一个变量,它实际上是类型长颈鹿
。
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(出哺乳动物N)
。
您可以通过键入长颈鹿
的变量 N
?
Can you pass a variable of type
Giraffe
toN
?
没有。 N
可写入 N
和 N
可能要写了虎
。
No. N
can write to n
, and N
might want to write a Tiger
.
结论3 :退出
参数不能发的小
您可以通过键入动物
的变量 N
?
Can you pass a variable of type
Animal
toN
?
嗯。
那么,为什么不呢? N
无法从读取n
,它只能写,对不对?你写了一个虎
来类型的变量动物
和你所有的设置,对吧?
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
才从读的东西ñ
。
这是允许此事件序列:
- 定义一个字段
X
类型动物
。 - 通
X
为退出
参数N
。 -
N
写入虎
到N
,其中是X
的别名。 - 在另一个线程,有人写了一个
龟
到X
。 -
N
尝试读取的内容N
,并发现了一个龟
在它认为类型的变量哺乳动物
。
- Declare a field
x
of typeAnimal
. - Pass
x
as anout
parameter toN
. N
writes aTiger
inton
, which is an alias forx
.- On another thread, someone writes a
Turtle
intox
. N
attempts to read the contents ofn
, and discovers aTurtle
in what it thinks is a variable of typeMammal
.
显然,我们想使非法。
Clearly we want to make that illegal.
结论4 :退出
参数无法取得更大的
Conclusion 4: out
parameters cannot be made "larger".
的最后结论的无论 REF
也不退出
参数可能会改变它们的类型。如果不这样做就是要打破可验证的类型安全。
Final conclusion: Neither ref
nor out
parameters may vary their types. To do otherwise is to break verifiable type safety.
如果在基本型理论的兴趣这些问题你考虑href=\"http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx\">我的一系列阅读。
If these issues in basic type theory interest you, consider reading my series on how covariance and contravariance work in C# 4.0.
这篇关于为什么不'裁判'和'去'的支持多态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!