=============
更新:私はこの回答をこのブログエントリの基礎として使用しました。
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。Tigerこれで、実際に型である変数にを入れましたGiraffe。
結論2:refパラメータを「小さく」することはできません。
今考えなさいN(out Mammal n)。
あなたは、型の変数を渡すことができますGiraffeにN?
いいえNに書き込むことができn、そしてN書きたいかもしれませんTiger。
結論3:outパラメータを「小さく」することはできません。
あなたは、型の変数を渡すことができますAnimalにN?
うーん。
さて、なぜですか? Nから読み取ることはできません。n書き込むことしかできません。Tiger型の変数にを書き込んで、Animalすべて設定しましたよね?
違う。ルールは「N書き込みのみ可能」ではありませんn。
ルールは、簡単に言えば:
1)正常に戻る前Nに書き込む必要があります。(スローした場合、すべてのベットはオフになります。)nNN
2)Nが何かをn読み取る前に、何かに書き込む必要がありますn。
これにより、この一連のイベントが可能になります。
x型のフィールドを宣言しますAnimal。
- パラメータ
xとしてに渡しoutますN。
N書き込みTigerへnの別名です、x。
- 別のスレッドでは、誰かが書き込みを行う
Turtleにはx。
Nはの内容を読み取ろうとし、型の変数であると考えているものnを見つけTurtleますMammal。
明らかにそれを違法にしたいのです。
結論4:outパラメータを「大きく」することはできません。
最終的な結論:どちらのパラメータもタイプを変えることはできませrefんout。そうでなければ、検証可能な型安全性を破ることになります。
基本的な型理論のこれらの問題に興味がある場合は、C#4.0での共分散と反変がどのように機能するかについての私のシリーズを読むことを検討してください。