2011-12-06 85 views
8

我需要一些建議/幫助,我不能再看到樹木。C#鑄造泛型(協方差和逆變?)

這是一個簡單的系列類,實現了一些使用泛型的接口。

然後我嘗試投放的具體類型,例如:

MyGenericObject<SomeObject> _obj; 

IMyGenericObject<ISomeObject> _genObj = (IMyGenericObject<ISomeObject>)_obj; 

//無效的轉換

我讀過有關協變和逆變,但也不是太清楚了一些文章爲什麼這止跌」不可能,或者如何避免它?


所以,在這個例子:

public interface IMyObject<in T> where T : IBaseObject 
{ 
    T Activity { get; set; } 
} 

是行不通的......


....因爲,你不能獲取和設置活動屬性。

在這個例子中,我需要做的:

public interface IMyObject<out T> where T : IBaseObject 
    { 
     T Activity { get; } 
    } 

希望幫助別人,並感謝所有幫助!

+0

請顯示接口的定義 –

回答

9

如果您聲明接口具有協變參數(out),則只能這樣做。只有在參數共同使用的情況下才能做到這一點。

例如,如果接口IMyGenericObject<T>的方法採用T參數,則會阻止您將該參數聲明爲協變。相反,如果有一種方法返回T,這會阻止您將該參數聲明爲逆變。

編輯

在迴應SLaks的回答您的意見,我很想重複一切埃裏克利珀曾經寫在合作和逆變。見http://blogs.msdn.com/b/ericlippert/archive/tags/Covariance+and+Contravariance/也是他在SO答案(最近https://stackoverflow.com/a/8380213/385844

總結:

你不能投IList<string>IList<object>,因爲它是合法的傳遞FileInfoIList<object>,但它是不合法的通它到IList<string>

你不能施放的IList<object>IList<string>,因爲它是合法的,從IList<string>檢索項目,並將其分配給一個字符串引用,而是一個IList<object>可能包含一個FileInfo,這是不能被分配到一個字符串參考。

EDIT 2

既然你這麼問的意見,它也有可能你的接口分成合作和逆變部分。要繼續列表例如,你可以有這些接口

public interface ICovariantList<out T> 
{ 
    T this[int index] { get; } 
    //... 
} 

public interface IContravariantList<in T> 
{ 
    T this[int index] { set; } 
    void Add(T item); 
    //... 
} 

public class SomeList<T> : ICovariantList<T>, IContravariantList<T> 
{ 
    //... 
} 

這可以讓你協變或contravariantly使用類,根據上下文。

+0

排序,感謝您的幫助! – sambomartin

+0

@sambomartin歡迎您。在編輯2更多的建議。 – phoog

+0

謝謝,我有點懷疑,雖然我不需要最後的二傳手......但我知道下一次! – sambomartin

4

您需要聲明該接口具有協變(out)通用參數。

+2

covariant是'out';逆變是'in'。助記符:「o」表示協變和out; 「n」爲逆變和in。 – phoog

+0

好的,謝謝。我遇到的下一個問題是編譯器報告:「錯誤1無效的變量:類型參數'xxx必須始終有效'xxx是協變的。」從我讀過的,我需要使界面只讀/不變。我有一個IMyGenericInterface屬性SomeObject SomeObjectInstance {get; set;}任何想法? – sambomartin

+0

@sambomartin:您需要了解方差是如何工作的。可寫變量屬性本質上是非類型安全的。 – SLaks