發現很少有集中討論C#可變性限制的中文博文(要麼就是一大段文字中夾雜很多凌亂的部分),所以寫發篇博文,集中討論,這些限制基本是基於安全考慮,亦或者根本難以實現而產生的。
注:本文不再解釋什麼是可變性,以及本文所討論的問題都基於.NET 4至.NET 4.5。所有地方我都力求簡潔。
好了,廢話不說了,開始吧。
1.可變性只支持引用轉換,禁止值類型轉換、裝箱轉換(好吧其實就是值類型轉換)、和用戶自定義類型轉換。
任何可變性轉換都是一種引用轉換,這種轉換是類型安全的,他只能操作引用類型,不會對引用的二進制表示產生影響也不會創建新的對象。
2.只有接口和委托可以有可變的類型參數。
3.out修飾的參數是不變的。
這樣說不太直觀。
比如一個委托 delegate int GetXXX<T>(string name,out T value)
此時T是不可以協變的。
因為CLR中並沒有out參數,(ref 和out也不可以使函數重載),out參數是含有[Out]特性的ref參數,而ref參數意味著(對於CLR來說)數據是既可以輸入也可以輸出的,所以T不可變。
4.必須顯示指定可變性(in/out)而不是由編譯器推斷。
強迫開發者顯示指定可以增強安全性,比如一個新的變化可用的時候,也許會影響重載。
5.不要在多播委托中使用可變性。
這應該算一個bug吧……不應該允許這樣的代碼,而且還不能在編譯時發現問題。一個策略是為將產生協變或者逆變的委托創建一個目標類型的委托來包裹他——當然,如果你都意識到了這個問題,你不大可能再寫出這樣的代碼。
暫時就寫到這啦。