=============
更新:私はこのブログエントリの基礎としてこの回答を使用しました:
refおよびoutパラメーターでタイプの変更が許可されないのはなぜですか?
この問題の詳細については、ブログページを参照してください。素晴らしい質問をありがとう。
=============
Animal
明らかなサブクラス化Mammal
の関係Reptile
を持つクラス、、、、、およびがGiraffe
あるとします。Turtle
Tiger
ここで、メソッドがあるとしますvoid M(ref Mammal m)
。 M
読み取りと書き込みの両方が可能m
です。
Animal
タイプの変数をに渡すことができますM
か?
いいえ。その変数には、を含めることができますがTurtle
、M
哺乳類のみが含まれていると想定されます。ATurtle
はではありません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
タイプの変数にaを書き込むと、Animal
すべて設定されますよね?
間違い。ルールは「N
書き込みしかできない」ではありませんn
。
ルールは簡単に言うと:
1)正常に戻る前N
に書き込む必要があります。(スローした場合、すべてのベットはオフになります。)n
N
N
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で共変性と反変性がどのように機能するかについての私のシリーズを読むことを検討してください。