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 IListIList因为将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参数。