《C 高階程式設計》學習筆記 抗變和協變

2021-09-08 10:10:16 字數 2785 閱讀 7567

1.協變和抗變

在.net 4之前,泛型介面是不變的。.net 4通過協變和抗變為泛型介面和泛型委託新增了乙個重要的擴充套件。協變和抗變指對引數和返回值的型別進行轉換。例如,可以給乙個需要shape引數的方法傳送rectangle引數碼?下面用示例說明這些擴充套件的優點。

在.net中,引數型別是協變的。假定有shape和rectangle類,rectangle派生自shape基類。宣告display()方法是為了接受shape型別的物件作為其引數:

public

void display(shape o)

現在可以傳遞派生自shape基類的任意物件。因為rectangle派生自shape,所以rectangle滿足shape的所有要求,編譯器接受這個方法呼叫:

rectangle r = new rectangle ;  

display(r);

方法的返回型別是抗變的。當方法返回乙個shape時,不能把它賦予rectangle,因為shape不一定總是rectangle。反過來是可行的:如果乙個方法像getrectangle()方法那樣返回乙個rectangle,

public rectangle getrectangle();

就可以把結果賦予某個shape:

shape s = getrectangle();

在.net framework 4版本之前,這種行為方式不適用於泛型。在c# 4中,擴充套件後的語言支援泛型介面和泛型委託的協變和抗變。下面開始定義shape基類和rectangle類:

public

class

shape

public

double height

public

override

string

tostring()

, height:

", width, height);

} }

public

class

rectangle: shape

2.泛型介面的協變

如果泛型型別用out關鍵字標註,泛型介面就是協變的。這也意味著返回型別只能是t。介面iindex與型別t是協變的,並從乙個唯讀索引器中返回這個型別:

public

inte***ce iindex

int count

}

**段variance/iindex.cs

如果對介面iindex使用了唯讀索引器,就把泛型型別t傳遞給方法,並從方法中檢索這個型別。這不能通過協變來實現-- 泛型型別必須定義為不變的。不使用out和in標註,就可以把型別定義為不變的。

iindex介面用rectanglecollection類來實現。rectanglecollection類為泛型型別t定義了rectangle:

public

class rectanglecollection: iindex,

new rectangle ,

new rectangle

};

public

static

rectanglecollection getrectangles()

public rectangle this[int

index]

} public

intcount

} }

**段variance/rectanglecollection.cs

rectanglecollection.getrectangle()方法返回乙個實現iindex介面的rectanglecollection類,所以可以把返回值賦予iindex型別的變數rectangle。因為介面是協變的,所以也可以把返回值賦予iindex型別的變數。shape不需要rectangle沒有提供的內容。使用shapes變數,就可以在for迴圈中使用介面中的索引器和count屬性:

static

void

main()

}

**段variance/program.cs

3.泛型介面的抗變

如果泛型型別用in關鍵字標註,泛型介面就是抗變的。這樣,介面只能把泛型型別t用作其方法的輸入:

public

inte***ce idisplay

**段variance/idisplay.cs

shapedisplay類實現idisplay,並使用shape物件作為輸入引數:

public

class shapedisplay: idisplay width: , height:

", s.gettype().name,

s.width, s.height);

} }

**段variance/shapedisplay.cs

建立shapedisplay的乙個新例項,會返回idisplay,並把它賦予shapedisplay變數。因為idisplay是抗變的,所以可以把結果賦予idisplay,其中rectangle派生自shape。這次介面的方法只能把泛型型別定義為輸入,而rectangle滿足shape的所有要求:

static

void

main()

**段variance/program.cs

C 抗變和協變

從.net3.5開始 加入了這兩個概念。在4.0中更是加強了 這裡就這兩個概念做乙個分析 委託呼叫的方法不需要與委託宣告定義的型別相同。因此可能出現協變和抗變。1.返回型別協變 方法的返回型別可以派生於委託定義的型別。在下面的示例中,委託mydelegate定義為返回delegatereturn型別...

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

泛型在.net 2.0中正式的引入。在使用泛型的過程中,聯絡上物件導向的繼承性。往往很容易想當然敲出類似以下 list animallst new list 顯然這樣編譯是不通過的。雖然dog和animal之間有繼承性,但是list和list這兩個類之間並沒有繼承性。如果要解決這樣的問題,用上協變與...

C 中協變抗變之我見

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