动态分配使用泛型扩展抽象类的具体类

时间:2017-07-30 03:02:02

标签: c# generics inheritance

我有以下类定义

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是具体类型。

1 个答案:

答案 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