2017-07-30 55 views
0

我有下面的类定义动态分配混凝土类,它扩展抽象类用通用

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

回答

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

通知中的IItem声明加入out关键字的T前面。

使用这个配置下面的代码按预期工作:

IItem<SomeObject> myItem; 

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

有关在.NET协变和逆变的更多信息,请参见Covariance and Contravariance in Generics在docs.microsoft.com。

+0

非常有趣。我从来没有听说过方差。是否有一个特定的原因,它只能在接口上完成? – yitzih