簡體   English   中英

c# 協變通用參數

[英]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);

“協變”是指在泛型類型中保留了類型實參的賦值兼容關系 GiraffeAnimal的賦值兼容,因此該關系保留在構造類型中: 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM