Re: [問題] C# 泛型中的共變數和反變數

作者: fo40225   2017-04-02 02:24:57
※ 引述《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時炸掉
作者: Litfal (Litfal)   2017-04-02 17:07:00
我覺得Covariance和Contravariance這兩個詞實在難懂,修飾關鍵字的out和in就又短又好懂XD
作者: kalaja (菸酒生)   2017-04-02 21:54:00
共變數與反變數確實有點艱澀,很容易忘記。
作者: LaPass (LaPass)   2017-04-03 01:33:00

Links booklink

Contact Us: admin [ a t ] ucptt.com