=============
更新:私はこのブログエントリの基礎としてこの回答を使用しました:
refおよびoutパラメーターでタイプの変更が許可されないのはなぜですか?
この問題の詳細については、ブログページを参照してください。素晴らしい質問をありがとう。
=============
Animal明らかなサブクラス化Mammalの関係Reptileを持つクラス、、、、、およびがGiraffeあるとします。TurtleTiger
ここで、メソッドがあるとしますvoid M(ref Mammal m)。 M読み取りと書き込みの両方が可能mです。
Animalタイプの変数をに渡すことができますMか?
いいえ。その変数には、を含めることができますがTurtle、M哺乳類のみが含まれていると想定されます。ATurtleはではありませんMammal。
結論1:refパラメータを「大きく」することはできません。(哺乳類よりも動物の数が多いため、変数にはより多くのものを含めることができるため、変数は「大きく」なります。)
Giraffeタイプの変数をに渡すことができますMか?
いいえ。にM書き込むことができ、に書き込みたい場合がmあります。これで、実際にはタイプの変数にを入れました。MTigermTigerGiraffe
結論2:refパラメータを「小さく」することはできません。
ここで考えてみましょうN(out Mammal n)。
Giraffeタイプの変数をに渡すことができますNか?
いいえ。に書き込むNことができ、を書き込みたい場合がnあります。NTiger
結論3:outパラメータを「小さく」することはできません。
Animalタイプの変数をに渡すことができますNか?
うーん。
さて、なぜですか? Nから読み取ることはできませんn、それはそれに書き込むことしかできませんよね?Tigerタイプの変数にaを書き込むと、Animalすべて設定されますよね?
間違い。ルールは「N書き込みしかできない」ではありませんn。
ルールは簡単に言うと:
1)正常に戻る前Nに書き込む必要があります。(スローした場合、すべてのベットはオフになります。)nNN
2)から何かを読み取る前にN何かを書き込む必要があります。nn
これにより、この一連のイベントが可能になります。
xタイプのフィールドを宣言しますAnimal。
- パラメータ
xとしてに渡します。outN
NのエイリアスであるにをTiger書き込みます。nx
- 別のスレッドで、誰かがにを書き込み
Turtleますx。
Nの内容を読み込もうとし、型の変数であると考えているものnを発見します。TurtleMammal
明らかに、それを違法にしたいのです。
結論4:outパラメータを「大きく」することはできません。
最終的な結論:どちらのパラメーターもそれらのタイプを変えることはできませrefん。outそうでなければ、検証可能な型安全性を破ることです。
基本型理論のこれらの問題に関心がある場合は、C#4.0で共変性と反変性がどのように機能するかについての私のシリーズを読むことを検討してください。