我有以下类定义
public class AbstractIem<T> where T : SomeObject
{
public abstract T Item { get; }
}
public class ConcreteItem1 : AbstractItem<ClassExtendingSomeObject>
{
public override ClassExtendingSomeObject Item { get; }
}
public class ConcreteItem2 : AbstractItem<AnotherClassExtendingSomeObject>
{
public override ClassExtendingSomeObject Item { get; }
}
我遇到问题的地方是我想动态分配AbstractItem<SomeObject>
,
AbstractItem<SomeObject> myItem;
switch (someIntValue)
{
case 1:
myItem = new ConcreteItem1();
break;
case 2:
myItem = new ConcreteItem2();
break;
}
尝试设置myItem
时出现以下错误:
无法将类型'ConcreteItem1'隐式转换为'AbstractItem'
我认为这应该有效,因为每个ConcreteItem
类扩展AbstractItem<SomeObject>
SomeObject
是具体类型。
答案 0 :(得分:2)
您尝试做的事情称为差异,而在C#中,它只能在接口上使用。因此,为了使其有效,您必须将AbstractItem<T>
更改为界面并将T
标记为协变。
public interface IItem<out T> where T : SomeObject
{
T Item { get; }
}
public class ConcreteItem1 : IItem<ClassExtendingSomeObject>
{
public ClassExtendingSomeObject Item { get; }
}
public class ConcreteItem2 : IItem<AnotherClassExtendingSomeObject>
{
public AnotherClassExtendingSomeObject Item { get; }
}
注意out
声明中T
前面添加了IItem
个关键字。
使用该设置后面的代码按预期工作:
IItem<SomeObject> myItem;
switch (someIntValue)
{
case 1:
myItem = new ConcreteItem1();
break;
case 2:
myItem = new ConcreteItem2();
break;
}
有关.NET中协方差和逆变的更多信息,请参阅docs.microsoft.com上的Covariance and Contravariance in Generics。