C#铸造泛型(协方差和逆变?)
在这方面我需要一些建议/帮助,我再也看不见树木了 这是一系列使用泛型实现一些接口的简单类 然后我尝试铸造具体类型,例如:C#铸造泛型(协方差和逆变?),c#,.net,c#-4.0,C#,.net,C# 4.0,在这方面我需要一些建议/帮助,我再也看不见树木了 这是一系列使用泛型实现一些接口的简单类 然后我尝试铸造具体类型,例如: MyGenericObject<SomeObject> _obj; IMyGenericObject<ISomeObject> _genObj = (IMyGenericObject<ISomeObject>)_obj; MyGenericObject\u obj; IMyGenericObject _genObj=(IMyGeneri
MyGenericObject<SomeObject> _obj;
IMyGenericObject<ISomeObject> _genObj = (IMyGenericObject<ISomeObject>)_obj;
MyGenericObject\u obj;
IMyGenericObject _genObj=(IMyGenericObject)_obj;
//无效演员阵容
我读过一些关于协方差和逆变的文章,但不太清楚为什么这不可能,或者如何绕过它
因此,在本例中:
public interface IMyObject<in T> where T : IBaseObject
{
T Activity { get; set; }
}
公共接口IMyObject,其中T:IBaseObject
{
T活动{get;set;}
}
不起作用
…因为,您无法获取和设置活动属性 在本例中,我需要执行以下操作:
public interface IMyObject<out T> where T : IBaseObject
{
T Activity { get; }
}
公共接口IMyObject,其中T:IBaseObject
{
T活动{get;}
}
希望这能帮助别人,谢谢大家的帮助 您需要将接口声明为具有协变(
out
)泛型参数。仅当您将接口声明为具有协变(out
)参数时,才能执行此操作。只有在协变使用参数的情况下才能执行此操作
例如,如果接口IMyGenericObject
有一个采用T
参数的方法,这将阻止您将该参数声明为协变参数。相反,如果有一个方法返回一个T
,则会阻止您将参数声明为反变量
编辑
为了回应你对SLaks答案的评论,我想重复Eric Lippert写过的关于协变和逆变的所有内容。参见SO(最近)中的及其答案
总结如下:
您不能将IList
强制转换为IList
,因为将FileInfo
传递给IList
是合法的,但将其传递给IList
是不合法的
您不能将IList
强制转换为IList
,因为从IList
检索项目并将其分配给字符串引用是合法的,但IList
可能包含无法分配给字符串引用的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>
{
//...
}
公共接口图标列表
{
T此[int索引]{get;}
//...
}
公共接口IContravariantList
{
T此[int索引]{set;}
无效添加(T项);
//...
}
公共类SomeList:ICovariantList、IContravariantList
{
//...
}
这允许您根据上下文以协变或反变方式使用类。请显示InterfaceCVariant的定义为
out
;逆变是中的。助记符:“o”表示协变和out;“n”表示逆变和in。好的,谢谢。我遇到的下一个问题是编译器报告:“错误1无效方差:类型参数'xxx必须在'xxx上保持不变有效是协变的。”根据我所读的内容,我需要将接口设置为只读/不变。我有一个IMyGenericInterface SomeObject SomeObjectInstance{get;set;}的属性。有什么想法吗?@sambomartin:您需要了解方差是如何工作的。一个可写的变量属性本质上是非类型安全的。@SLaks-你是对的,我是这样做的-但我通过一些最初看起来很简单的例子来学习这一点。根据phoog的说法-由于我的接口有一个返回T的方法,这阻止我将参数声明为逆变(in)?@SLaks:可写协变属性不是类型安全的。一个可写的逆变属性正是逆变的意义所在。谢谢,我有点习惯了,尽管我最终不需要setter。。。但我知道下一次!