協變和逆變

2021-06-23 02:25:41 字數 2270 閱讀 1399

協變和逆變都是術語,前者指能夠使用比原始指定的派生型別的派生程度更大的型別,後者指能夠使用比原始指定的派生型別的派生程度更小的型別。

using system;

using system.collections.generic;

using system.text;}}

class derived : base

static void main(string args)

}vs2008報錯

vs2010正常。

為什麼呢 原來介面實現了協變

public inte***ce ienumerable: ienumerable

public inte***ce ienumerable : ienumerable

vs2010不一樣了

從 .net framework 4 開始,某些泛型介面具有協變型別引數;例如:ienumerable、ienumerator、iqueryable 和 igrouping。 

由於這些介面的所有型別引數都是協變型別引數,因此這些型別引數只用於成員的返回型別。

下面的示例闡釋了協變型別引數。 

此示例定義了兩個型別:base 具有乙個名為 printbases 的靜態方法,該方法採用 ienumerable(在 visual basic 中為 ienumerable(of base))並輸出元素。

derived 繼承自 base。

此示例建立乙個空 list(在 visual basic 中為 list(of derived)),並且說明可以將該型別傳遞給 printbases 且在不進行強制轉換的情況下將該型別分配給型別 ienumerable 的變數。 

list 實現 ienumerable,它具有乙個協變型別引數。

協變型別引數是可使用 ienumerable 的例項而非 ienumerable 的原因。

} }

class circle : shape

public double radius }

public override double area }

}class shapeareacomparer : system.collections.generic.

icomparer

}static void main(string args)

;foreach (circle c in circlesbyarea)

console.read();}}

}從 .net framework 4 開始,某些泛型介面具有逆變型別引數;例如:icomparer、icomparable 和 iequalitycomparer。 

由於這些介面只具有逆變型別引數,因此這些型別引數只用作介面成員中的引數型別。

下面的示例闡釋了逆變型別引數。 

該示例定義具有 area 屬性的抽象(在 visual basic 中為 mustinherit)shape 類。

該示例還定義乙個實現icomparer(在 visual basic 中為 icomparer(of shape))的 shapeareacomparer 類。

icomparer.compare 方法的實現基於 area 屬性的值,所以 shapeareacomparer 可用於按區域對 shape 物件排序。

circle 類繼承 shape 並重寫 area。 

該示例建立 circle 物件的 sortedset,使用採用 icomparer(在 visual basic 中為 icomparer(of circle))的建構函式。

但是,該物件不傳遞 icomparer,而是傳遞乙個用於實現 icomparer 的 shapeareacomparer 物件。

當**需要派生程度較大的型別的比較器 (circle) 時,該示例可以傳遞派生程度較小的型別的比較器 (shape),因為 icomparer 泛型介面的型別引數是逆變引數。

向 sortedset 中新增新 circle 物件時,每次將新元素與現有元素進行比較時,都會呼叫 shapeareacomparer 物件的 icomparer.compare方法(在 visual basic 中為 icomparer(of shape).compare 方法)。 

方法 (shape) 的引數型別比被傳遞的型別 (circle) 的派生程度小,所以呼叫是型別安全的

。逆變使 shapeareacomparer 可以對派生自 shape 的任意單個型別的集合以及混合型別的集合排序。

協變和逆變

二 真正的協變和逆變 概念 1 以前的泛型系統 或者說沒有in out關鍵字時 是不能 變 的,無論是 逆 還是 順 協 2 當前僅支援介面和委託的逆變與協變 不支援類和方法。但陣列也有協變性。3 值型別不參與逆變與協變。協變 foo foo public class testoutwhere t ...

協變和逆變

假設有這樣乙個類 class person icloneable 但是由於我們知道是返回乙個person類的例項,所以返回型別 object 寫在這裡總會覺得很彆扭,我們希望寫成 class person icloneable 顯然,這是錯的 雖然這是錯的,但這就是返回型別的協變性,只是非泛型介面和...

C 協變逆變

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