1. 程式人生 > >C#協變和逆變

C#協變和逆變

parent sub 向上 ava 逆變 () 例子 tro ren

C#種的協變和逆變只能針對泛型的接口和委托。在C#1的時候委托是支持參數的協變和逆變的。

協變和逆變本質上是針對類型和類型之間的綁定的。比如說數組,數組其實就是一種和具體類型之間發生綁定的類型。數組類型Int32[]就對應於Int32這個原本的類型。任何類型T都有其對應的數組類型T[]。我們說:如果有類型Parent和其子類Sub,那麽Parent p=new Sub();這種的類型轉換是安全的。如果有一種類型和Parent類型進行了綁定,比如說Parent[]數組,如果Sub[]到Parent[]的轉換是安全的,我們就說是協變,如果相反的方向上轉換是安全的,我們就說是逆變了。C#中我們知道數組是協變的,也就是說Sub[]到Parent[]的轉換是安全的。再舉個例子,就是String類型繼承自Object類型,所以任何String的引用都可以安全地轉換為Object引用。我們發現String[]數組類型的引用也繼承了這種轉換能力,它可以轉換成Object[]數組類型的引用,數組這種與原始類型轉換方向相同的可變性就稱作協變(

covariant

由於數組不支持反變性,我們無法用數組的例子來解釋反變性,所以我們現在就來看看泛型接口和泛型委托的可變性。假設有這樣兩個類型:TSub是TParent的子類,顯然TSub型引用是可以安全轉換為TParent型引用的。如果一個泛型接口IFoo<T>,IFoo<TSub>可以轉換為IFoo<TParent>的話,我們稱這個過程為協變,而且說這個泛型接口支持對T的協變。而如果一個泛型接口IBar<T>,IBar<TParent>可以轉換為T<TSub>的話,我們稱這個過程為反變(contravariant

而且說這個接口支持對T的反變。因此很好理解,如果一個可變性和子類到父類轉換的方向一樣,就稱作協變;而如果和子類到父類的轉換方向相反,就叫反變性。

C#協變和逆變