作者fo40225 ()
標題Re: [問題] C# 泛型中的共變數和反變數
時間Sun Apr 2 02:24:57 2017
※ 引述《LaPass (LaPass)》之銘言:
: https://pastebin.com/5xXiWRPB
: 如連結中的程式碼
: 所以即使知道 actd 實際上是一個 Action<C>
: 在 C# 當中也沒有任何方法可以把他轉換回 Action<C>
: 是這樣子嗎?
https://msdn.microsoft.com/en-us/library/dd799517.aspx
Action泛型委派的宣告如下
public delegate void Action<in T>(T obj);
in T 代表的是T是一個contravariance反變數
簡單的說 這個T是一個"輸入"參數類型
假設我們有兩個class
public class Base {}
public class Derived : Base {}
宣告一個 Action<Base> foo 表示這個委派 foo 接受一個 Base 實體
這時候在泛型宣告有 in 限定詞的情況下
可以直接 Action<Derived> bar = foo;
因為能給 bar 的 Derived 一定是一個 Base 這是類型安全的
而你的範例 Action<Base> foo = bar;
這句話並不是類型安全 能接受Derived輸入 不代表能接受輸入Base
所以需要顯式地cast
相對於Contravariance反變數的是Covariance共變數
範例
IEnumerable泛型介面的宣告如下
public interface IEnumerable<out T>
out T代表著T是一個"輸出"參數類型
宣告一個 IEnumerable<Derived> foo 表示這個介面是輸出一個Derived
在泛型宣告有out限定詞的情況下
IEnumerable<Base> bar = foo; 這句話是類型安全的
輸出一個Derived一定是Base
這時候不用特別轉換
結論 如果編譯器告訴你錯了 就要小心是不是有什麼地方搞錯了
做cast時要了解自己在做什麼 不然能編譯成功也會在runtime時炸掉
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.228.29.213
※ 文章網址: https://www.ptt.cc/bbs/C_Sharp/M.1491071103.A.86E.html
推 Litfal: 我覺得Covariance和Contravariance這兩個詞實在難懂, 04/02 17:07
→ Litfal: 修飾關鍵字的out和in就又短又好懂XD 04/02 17:08
推 kalaja: 共變數與反變數確實有點艱澀,很容易忘記。 04/02 21:54
推 LaPass: 推 04/03 01:33