2011-12-06 46 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