C#Casting generics(协方差和逆变?)
我需要一些建议/帮助,我再也看不到树上的木头了。
这是一系列直接使用generics实现某些接口的类。
然后我试图将具体类型转换为例如:
MyGenericObject _obj; IMyGenericObject _genObj = (IMyGenericObject)_obj;
//无效的演员表
我读过一些关于协方差和逆变的文章,但不太清楚为什么这不可能,或者如何绕过它呢?
所以,在这个例子中:
public interface IMyObject where T : IBaseObject { T Activity { get; set; } }
不会工作……
….因为,你无法获取并设置Activity属性。
在这个例子中,我需要做:
public interface IMyObject where T : IBaseObject { T Activity { get; } }
希望对某人有所帮助,并感谢所有人的帮助!
如果将接口声明为具有协变( out
)参数,则只能这样做。 只有在协变使用参数时才能执行此操作。
例如,如果接口IMyGenericObject
具有采用T
参数的方法,则会阻止您将参数声明为协变。 相反,如果有一个返回T
的方法,则会阻止您将参数声明为逆变。
编辑
在回应你对SLaks答案的评论时,我很想重复Eric Lippert所写的关于共同和逆变的所有内容。 请参阅http://blogs.msdn.com/b/ericlippert/archive/tags/Covariance+and+Contravariance/以及他在SO中的答案(最近https://stackoverflow.com/a/8380213/385844 )
总结一下:
您不能将IList
IList
为IList
因为将FileInfo
传递给IList
是合法的,但将它传递给IList
是不合法的。
您不能将IList
IList
转换为IList
,因为从IList
检索项并将其分配给字符串引用是合法的,但IList
可能包含FileInfo,无法分配给字符串引用。
编辑2
由于您征求了建议,因此也可以将接口拆分为共变和逆变部分。 要继续列表示例,您可以拥有这些接口
public interface ICovariantList { T this[int index] { get; } //... } public interface IContravariantList { T this[int index] { set; } void Add(T item); //... } public class SomeList : ICovariantList , IContravariantList { //... }
这允许您根据上下文协同或逆转地使用该类。
您需要将接口声明为具有协变( out
)generics参数。