c 協變和抗變 C 中協變與抗變(逆變)

2021-10-13 01:58:14 字數 1130 閱讀 4705

泛型在.net 2.0中正式的引入。在使用泛型的過程中,聯絡上物件導向的繼承性。往往很容易想當然敲出類似以下**

list animallst=new list;

顯然這樣編譯是不通過的。雖然dog和animal之間有繼承性,但是list和list這兩個類之間並沒有繼承性。如果要解決這樣的問題,用上協變與抗變(逆變),它們統稱為變體。是.net 4.0引入的新特性,但是早在.net 2.0就引入了。

變體適用於泛型介面與泛型委託,在我們宣告泛型藉口或泛型委託時,加上out或in關鍵字就能實現。

out是用於協變,這就好比子類通過隱式轉換成基類的情形,這麼平淡的轉換,與「協」的感覺類似;

in是用於抗變,類似於基類強制轉換成子類,帶有一些負面的感覺的,於是「逆」或者「抗」關聯上了。

兩者可以說得上是用於整條類的繼承鏈上轉換工作的,但是方向不同。

那麼先來看看協變

delegate t animalaction1();inte***ce iproduce

t cretenewtypeins();

out這個關鍵字使人聯想到「輸出」,既然是出的話,那麼協變的型別只能用於方法的返回值或者是屬性的get,如果變數作為方法的引數(即使是帶out關鍵字的引數)和屬性的set,那麼編譯會報錯。那麼在fcl裡面是協變的介面和委託如下

iqueryableienumeratorigroupingconverter

看上去都是返回泛型t的。

再看看抗變

delegate void animalbark(t animal);inte***ce irunnablevoidcanrun(t t);

既然與協變相反,那麼它就代表著「輸入」,抗變型別就只能用於方法的引數和屬性的set。在fcl裡抗變的介面和委託如下

icompareriequalitycomparericomparablesystem.actionsystem.funcpredicatecomparisonconverter

可是變體不適用於上面的list,因為這個泛型類在宣告的時候並沒有用上out關鍵字,就算是用上了也不現實,因為對於list這個這個泛型類來說,它本身就存在著輸入與輸出兩種行為,add,remove等方法就要利用到引數的輸入,同時它本身又能通過索引器來獲取某個所以值下的元素,既有out又有in的泛型相互矛盾,定義不出來。

C 中協變抗變之我見

在.net4.0中,新加入了協變與抗變的內容,最近查了一下msdn,對它有了乙個大概的理解,希望能夠幫助到和我一樣的菜鳥。協變 協變非常類似於普通的多型性的分配,它是針對成員的返回值型別,定義時使用關鍵字out,假定您有乙個名為 base 的基類和乙個名為 derived 的派生類 ienumera...

C 中的協變與抗變

using system using system.collections.generic using system.linq using system.text namespace csharp基礎 else console.readline 按照委託簽名,但返回的是子類的例項 public st...

C 中的協變和抗變

net4通過協變和抗變為泛型介面和泛型委託新增了乙個重要擴充套件。協變和抗變指對引數和返回值的型別進行轉換。在.net中,引數型別是協變的。假定有 shape和 rectangle 類,rectangle 派生自shape基類。宣告display 方法是為了接受 shape型別的物件作為其引數 pu...