Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#铸造泛型(协方差和逆变?)_C#_.net_C# 4.0 - Fatal编程技术网

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。。。但我知道下一次!