協變和逆變
阿新 • • 發佈:2021-01-09
協變和逆變
約定:
A ≦ B
意味著 A 是 B 的子型別A → B
指的是以 A 為引數型別,以 B 為返回值型別的函式型別x : A
意味著 x 的型別為 A
協變和逆變的概念可以藉助實際的變數型別來理解:
- 協變和普通變數:
在 C# 中,List
IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d;
簡單來說,協變就和麵向物件概念中的多型一樣,指可以使用父型別引用指向子型別例項的情況。
- 逆變和函式變數:
假如我有這樣一個型別鏈:C ≦ B ≦ A,此時有一個函式是這樣的:f(B → B),這個函式接收一個 B → B 函式作為引數, 那麼這種情況下,怎樣的函式可以作為 f 的引數呢?
首先,對於 C → *
來說都是不行的,因為 f 呼叫函式時引數型別可能是 B 或 B 的其他子型別,而 C → *
只支援 C 型別的入參。
然後,對於 * → A
來說也是不行的,因為 f 要求的返回值是 B 或 B 的其他子型別,但是 * → A
可能會返回 B 的父型別 A。
最後,對於 A → C
來說卻是可行的,因為 f 的引數只會是 B 或 B 的其他子型別,而 A → C
的入參型別是 A,滿足。 同時,函式 A → C
這時,神奇的情況便發生了,當函式型別是 B → B
時,我們可以使用 <? super B> → <? extend B>
進行賦值:
Action<Base> b = (target) => { Console.WriteLine(target.GetType().Name); };
Action<Derived> d = b;
這就是逆變。
參考: