2014-05-05 70 views
2

我只需要再次使用協變類型修飾符out。我有一個類的泛型類型,並想添加一個out但VS告訴我,這隻能在接口上實現。爲什麼我需要協方差接口(輸出類型)?

但是,爲什麼我只能在界面上使用out修飾符?

我幫助自己創建了我的類的接口副本,但這對於我來說似乎有點奇怪,因爲我只有一個接口,所以我可以使用此修飾符。

+1

Lippert先生的經典(和正確的)迴應將是「因爲沒有人執行」,並跟隨「成本不能證明附加價值」。 –

+2

@DStanley:雖然這是真的,但這裏還有其他技術原因。如果這個類不是一成不變的,那麼你將如何安全地使用變體T?如果T是「in」,那麼類型T的字段不能被讀取,並且如果T是「out」,那麼不能寫入類型T的字段;字段你可以不讀或不寫無用的功能。協方差對於不可變類非常有用,其中所有字段都是隻讀的;他們可以寫在構造函數中。 *這是我關於成本和價值觀的適用點。 –

回答

7

確保類的定義實際上是協變性是非常困難的。編譯器更容易確保接口實際上是協變的。

對於一個類,僅僅使用一個使用泛型類型的字段立即強制泛型參數是不變的,因爲就編譯器而言,該值可以被讀取和修改。儘管支持差異的類可能是,但在實踐中,需要向開發人員實際使用它的約束將會非常困難,而不僅僅是創建包裝界面。

讓我們考慮一個簡單的例子:

public interface IWrapper<out T> 
{ 
    T Value { get; } 
} 
public class Wrapper<T> : IWrapper<T> 
{ 
    public Wrapper(T value) 
    { 
     Value = value; 
    } 
    public T Value { get; private set; } 
} 

上面顯示是不是相對於T協變(除非您將它轉換爲界面)的類。它接受類型爲T的輸入值(通過構造函數)。只有因爲構造函數沒有通過接口暴露,接口才能夠協變。

+0

構造函數'T'不應該影響協方差,因爲構造函數調用總是作用於指定了確切類型的東西。靜態成員的行爲會產生更大的問題。我不確定人們甚至可以爲這些定義一致的語義,更不用說實現它們。 – supercat

+0

謝謝,所以如果我有一個T參數的方法,接口是不是協變? –

+1

@JanS正確。試試看看編譯器說了些什麼。 – Servy

相關問題