=============
更新:我使用此答案作为此博客条目的基础:
为什么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必须先写入。(如果抛出,则所有投注均无效。)
n``N``N
2)
N必须先写入内容,
n然后才能从中读取内容
n。
这允许发生以下一系列事件:
- 声明一个
x
type 字段Animal
。 x
作为out
参数传递给N
。N
写入一个,Tiger
到n
的别名x
。- 在另一个线程,有人写了一
Turtle
成x
。 N
试图阅读的内容n
,并发现Turtle
它认为是类型的变量Mammal
。
显然,我们想使之非法。
结论4 :
out不能将参数设为“更大”。
最后得出结论 : 无论是ref
也不out
参数可能有所不同它们的类型。否则将破坏可验证的类型安全性。
如果您对基本类型理论中的这些问题感兴趣,请考虑阅读我的有关协方差和反方差如何在C#4.0中工作的系列文章。



