C 協變與逆變

2022-01-12 21:26:41 字數 1285 閱讀 5443

用最簡單的最有內涵的方式進行概括

在oo哲學裡面 有個依賴倒置,這是個oo的核心

就是用父類物件可以代表後面也許動態增加的子類物件從而增加了軟體的,可擴充套件性,和相對穩定性,並且開啟了一種oo正規化

class a{}

class a1:a{}

class a2:a{}

用a a 這個物件可以表達a1,a2...等子類的例項  以便於應對乙個維度上的需求變更

在c#語言發展中當引入泛型以後,出現了新需求,就是 如何讓這種oo正規化自然的涵蓋到泛型這個新特性,因為泛型,基本上與其引數之間存在某種可預見之

關聯。如果不引入協變與逆變的概念那麼,很多泛型就不能使用oo的上述這樣的常規程式設計正規化。

舉個例子說明

如果有個t= 狗類 (class dog)

那麼 有個泛型 ixx這裡是 ixx

如果是逆變 則 ixx這告訴介面 ixx所有與t相關的 介面成員都只是輸入向而非輸出向的,

這樣可以使用 ixx替換 ixx了,注意這個替換就有點 oo依賴倒置的意思因為如上所說,它

把這種邏輯延續到了相關的泛型介面和泛型委託上,如果乙個介面有in限制或約束那麼就可以有這種替換,為什麼,有了in 這個限制dog就可以用subdog

來替換了呢? ,現實故事是這樣的, ixx裡面全是和狗相關的功能,這時你加入的是哈巴狗,小土狗,或藏獒,這些全是狗這個類別的,用來替換 ixx

是不會產生歧義的,如果你用 ixx哺乳動物這個類別去代替就會出問題,因為 老鼠,猴子都是哺乳動物,猴子會上樹,狗不行,你這樣替代就出問題了

如果用父級允許加入到 ixx裡面那麼 dog裡面就不單純了,不止有狗,可能還有鼠或貓 這與定義已經衝突了所以不行。

out呢? 如果 ixx這個限制說明這個介面中一切相關dog引數的成員只有輸出而沒有輸入操作,有了這樣的限制前提,那麼使用 ixx去「替換」

就沒問題了,為什麼是這樣呢?還是回到現實故事中來理解,ixx裡面有各種狗,哈巴狗,土狗,藏獒什麼的,全是狗,他們的最大公約就是其父級狗這個類

,所以使用其父級或給高階的父級都沒問題 象 哺乳動物, 動物,或生物這些 父級都可以,因為這樣的替換不會產生歧義,具體的狗的各種功能可能在父級裡面不全有,但是父級裡面有的

其子類必有,所以這樣的替換就無歧義,與之相反你不能使其子級做為輸出,比如寵物狗 ixx用來替代 ixx

因為ixx裡面可能包含非 寵物狗,這樣的替換邏輯就發生了錯誤。

簡單來說就是視 in 和 out 關鍵字修飾的不同,可使用不同的泛型引數類,對其進行替換。

綜上所述 結合現實故事的梳理我們不難理解 c# 的協變與逆變這兩個比較冷門的概念了。

協變與逆變

目錄 1.協變 2.逆變 在泛型之前,我們都知道可以將乙個派生類物件賦值給基類變數,這叫做賦值相容性。看下面這個例子 相容性示意圖如上。但是當我們新增泛型機制時 class animal class dog animal delegate t factory class program static...

逆變與協變

一 遇到問題 這是基於.net3.5開發,實際工作中遇到乙個問題。假設我們有乙個 base 類,乙個 derived 類,derived 繼承了 base。如下 classbase classderived base 當我用ienumerable作為形參,list作為實參時,發現編譯出錯了!原本父類...

C 協變逆變

1.泛型的協變逆變 注意 只能放在介面或者委託的泛型引數前面 1 委託泛型引數 static class testconsole private static argumentexception test1 object obj private static exception test2 stri...