似乎沒有要在這個問題上的任何問題,所以我會提出幾個問題來回答。
什麼是協變轉換?
讓我們假設我們有一些類型的Fruit
和Apple
和Banana
具有明顯的關係; Apple
是一種Fruit
,依此類推。
協變轉換是其中類型參數的可轉換性意味着泛型類型的可轉換性的轉換。如果Apple
可轉換爲Fruit
,並Bowl<Apple>
可轉換爲Bowl<Fruit>
,然後Bowl<T>
在T.
什麼是逆變轉換協變?
甲逆變轉換是一種協變轉換該反轉方向,而不是保存它。如果Eater<Fruit>
可轉換爲Eater<Apple>
然後Eater<T>
是T.
逆變我要怎樣接口或委託爲在其類型參數的協變或逆變?
協變類型參數標記爲out
,逆變類型參數標記爲in
。
這是爲了助記符:協變接口通常在輸出位置出現類型參數,並且反向接口有類型參數出現在輸入位置。
String
可轉換爲Object
。我怎樣才能讓IReadOnlyCollection<String>
兌換成IReadOnlyCollection<Object>
?
請在T.馬克它out
IReadOnlyCollection<T>
協變。
考慮下面的代碼:
delegate void Action<in T>(T t);
interface IFoo<in X>
{
void M(Action<X> action);
}
爲什麼編譯器說,這是不是有效?
因爲它是無效的。讓我們看看爲什麼。
class Foo : IFoo<Fruit>
{
public void M(Action<Fruit> action)
{
action(new Apple()); // An apple is a fruit.
}
}
...
IFoo<Fruit> iff = new Foo();
IFoo<Banana> ifb = iff; // Contravariant!
ifb.M(banana => { banana.Peel(); });
按照邏輯。這個程序通過一個蘋果作爲Banana.Peel()
的「這個」,這顯然是錯誤的。
編譯器知道這可能發生,因此不允許首先聲明接口。
我應該怎麼做,如果我有變化的問題嗎?
您應該先閱讀我關於該功能設計和實現的文章。從底部開始;它們列出以相反的順序爲:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
如果您仍然有問題,那麼你應該在這裏張貼問題,實際上包含的問題,而不是讓人們猜測什麼真正的問題是。
順便提一句,'ItemType'應該叫做'T'。 – SLaks
而不是讓'CopyToArray'返回'Array',讓它返回'ItemType []',這樣它的強類型。 – Servy
這個問題似乎沒有任何問題。 「我想要繼承工作」不是一個問題。如果你想要一個答案,將其重寫爲一個問題。編譯器是正確的;此代碼不是類型安全的。 –