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

C# 动态分配用泛型扩展抽象类的具体类,c#,generics,inheritance,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; } } publi

我有以下的类定义

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; }
}
公共类AbstractIem,其中T:SomeObject
{ 
公共抽象T项{get;}
}
公共类ConcreteItem1:AbstractItem
{
公共重写ClassExtendingSomeObject项{get;}
}
公共类ConcreteItem2:AbstractItem
{
公共重写ClassExtendingSomeObject项{get;}
}
我遇到的问题是,当我想动态分配
AbstractItem
的对象时

abstractItemMyItem;
开关(someIntValue)
{
案例1:
myItem=新的ConcreteItem1();
打破
案例2:
myItem=新的ConcreteItem2();
打破
}
尝试设置
myItem
时,我遇到以下错误:

无法将类型“ConcreteItem1”隐式转换为“AbstractItem”


我认为这应该是可行的,因为每个
ConcreteItem
类都扩展了
AbstractItem
,其中
SomeObject
是一个具体的类型。

您试图做的是称为方差,在C中,这仅在接口上可能。因此,要使其工作,您必须将
AbstractItem
更改为一个接口,并将
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; }
}

有关.NET中协方差和逆变换的更多信息,请访问docs.microsoft.com。

您尝试执行的操作称为方差,而在C#中,这仅在接口上可行。因此,要使其工作,您必须将
AbstractItem
更改为一个接口,并将
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; }
}

有关.NET中协方差和逆变换的更多信息,请访问docs.microsoft.com。

非常有趣。我以前从未听说过变化。有没有一个特定的原因,它只能在接口上完成?非常有趣。我以前从未听说过变化。是否有特定的原因只能在接口上执行?
IItem<SomeObject> myItem;

switch (someIntValue)
{
    case 1:
        myItem = new ConcreteItem1();
        break;
    case 2:
        myItem = new ConcreteItem2();
        break;
}