[英]c# covariant generic parameter
我試圖理解這一點,但我沒有從搜索中得到任何適當的結果。
在 c# 4 中,我可以做到
public interface IFoo<out T>
{
}
這與
public interface IFoo<T>
{
}
我所知道的是out
使泛型參數協變(??)。 有人可以舉例說明<out T>
部分的用法嗎? 還有為什么只適用於接口和委托而不適用於類?
對不起,如果它是重復的,如果是,請關閉它。
有人可以舉例說明 out T 部分的用法嗎?
當然。 IEnumerable<T>
是協變的。 這意味着你可以這樣做:
static void FeedAll(IEnumerable<Animal> animals)
{
foreach(Animal animal in animals) animal.Feed();
}
...
IEnumerable<Giraffe> giraffes = GetABunchOfGiraffes();
FeedAll(giraffes);
“協變”是指在泛型類型中保留了類型實參的賦值兼容關系。 Giraffe
與Animal
的賦值兼容,因此該關系保留在構造類型中: IEnumerable<Giraffe>
與IEnumerable<Animal>
的賦值兼容。
為什么只適用於接口和委托而不適用於類?
類的問題是類往往具有可變字段。 讓我們舉個例子。 假設我們允許這樣做:
class C<out T>
{
private T t;
OK,現在這個問題在你go之前仔細想清楚。 C<T>
可以在構造函數之外有任何方法將字段t
設置為默認值以外的值嗎?
因為它必須是類型安全的,所以C<T>
現在不能有將 T 作為參數的方法; T 只能退貨。 那么誰設置 t,他們從哪里獲得設置它的值?
只有當 class 是不可變的時,協變 class 類型才真正起作用。 而且我們沒有在 C# 中創建不可變類的好方法。
我希望我們這樣做,但我們必須接受我們提供的 CLR 類型系統。 我希望將來我們可以更好地支持不可變類和協變類。
如果您對此功能感興趣,請考慮閱讀我關於我們如何設計和實現該功能的長系列。 從底部開始:
https://blogs.msdn.microsoft.com/ericlippert/tag/covariance-and-contravariance/
如果我們談論的是通用方差:
協方差是關於從操作返回給調用者的值。
逆變它是相反的,它是關於調用者傳遞的值:
據我所知,如果類型參數僅用於 output,則可以使用 out。 但是,如果該類型僅用於輸入,則可以使用 in。這很方便,因為編譯器無法確定您是否可以記住哪種形式稱為協變,哪種形式稱為逆變。 如果在聲明類型后不顯式聲明它們,則相關的轉換類型是隱式可用的。
類中沒有方差(協方差或逆變),因為即使您有一個僅將類型參數用於輸入(或僅將其用於輸出)的 class,您也無法指定 in 或 out 修飾符。 只有接口和委托可以有變體類型參數。 首先,CLR 不允許這樣做。 從概念的角度來看,接口代表了一種從特定角度看待 object 的方式,而類是更實際的實現類型。
這意味着如果你有這個:
class Parent { }
class Child : Parent { }
那么IFoo<Child>
的實例也是IFoo<Parent>
的一個實例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.