=============
UPDATE:我用這個答案這個博客條目的基礎:
Why do ref and out parameters not allow type variation?
更多請見博客頁面關於這個問題的評論。感謝您的好問題。
=============
讓我們假設你有類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
有可能寫入n
前N
正常返回。 (如果N
拋出,全盤皆輸。)
2)N
有它從n
讀的東西之前寫的東西n
。
允許這一系列事件:
- 聲明
Animal
類型的字段x
。
- 通過
x
作爲out
參數到N
。
N
將Tiger
寫入n
,這是x
的別名。
- 在另一個線程上,有人將
Turtle
寫入x
。
N
嘗試讀取n
的內容,並發現它認爲是Mammal
類型的變量的Turtle
。
很明顯,我們想使這種非法。
結論4:out
參數不能設置爲「較大」。
最後得出結論:無論ref
也不out
參數可能有所不同它們的類型。否則就是打破可驗證的類型安全。
如果這些問題在基本類型理論中引起您的興趣,請考慮閱讀my series on how covariance and contravariance work in C# 4.0。
+1。使用真實世界的例子清楚地展示問題(例如 - 用A,B和C解釋使得難以證明爲什麼它不起作用),這是一個很好的解釋。 – 2009-07-30 15:25:51
我感到謙卑的閱讀這個思維過程。我想我最好回到書本上來! – 2009-09-22 00:44:46
在這種情況下,我們真的不能使用Abstract類變量作爲參數並傳遞它的派生類對象! – 2009-09-23 05:48:11