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;
}