2017-07-30 58 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