c#类型转换泛型(协方差和逆变?)
本文关键字:方差 类型转换 泛型 | 更新日期: 2023-09-27 18:16:51
我需要一些建议/帮助,我再也看不到树木了
它是一系列使用泛型实现一些接口的直接类。
然后我试着转换具体类型,例如:
MyGenericObject<SomeObject> _obj;
IMyGenericObject<ISomeObject> _genObj = (IMyGenericObject<ISomeObject>)_obj;
//强制转换无效
我读过一些关于协方差和逆变的文章,但不太清楚为什么这是不可能的,或者如何绕过它?
那么,在这个例子中:
public interface IMyObject<in T> where T : IBaseObject
{
T Activity { get; set; }
}
不工作…
…因为,你不能获取和设置Activity属性。
在这个例子中,我需要做:
public interface IMyObject<out T> where T : IBaseObject
{
T Activity { get; }
}
希望能帮助到一些人,感谢所有的帮助!
只有在将接口声明为具有协变(out
)参数时才能这样做。只有当参数被协变使用时,你才能这样做。
例如,如果接口IMyGenericObject<T>
有一个接受T
参数的方法,这将阻止您将参数声明为协变。相反,如果有一个返回T
的方法,则可以阻止您将参数声明为逆变。
编辑
作为对SLaks的回答的回应,我很想重复Eric Lippert关于协逆变的所有文章。参见http://blogs.msdn.com/b/ericlippert/archive/tags/Covariance+and+Contravariance/以及他在SO中的回答(最近的一次是https://stackoverflow.com/a/8380213/385844)
总结:
不能将IList<string>
强制转换为IList<object>
,因为将FileInfo
传递给IList<object>
是合法的,但将其传递给IList<string>
是不合法的。
您不能将IList<object>
强制转换为IList<string>
,因为从IList<string>
中检索项并将其分配给字符串引用是合法的,但是IList<object>
可能包含FileInfo,不能分配给字符串引用。
编辑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>
{
//...
}
这允许您根据上下文协变或逆变地使用类。
您需要将接口声明为具有协变(out
)泛型参数