2011-05-09 52 views
7

可能重複:
Casting List<T> - covariance/contravariance problem返回抽象類的列表

我定義如下

public abstract class AbstractDType 
{ 
    protected abstract string Num1 { get; set; } 
    protected abstract string Num2 { get; set; } 
} 

public class AD1 : AbstractDType 
{ 
    public string Num1 { get; set; } 
    public string Num2 { get; set; } 
    public string Num3 { get; set; } 
} 

public class AD2 : AbstractDType 
{ 
    public string Num1 { get; set; } 
    public string Num2 { get; set; } 
    public string Num3 { get; set; } 
} 

public abstract class DTypeStrategy 
{ 
    protected virtual List<AbstractDType> GetData() 
    { 
      return new List<AD1>(); 
    }  
} 

類我想回PD1的列表(具體類型)在GetData()方法中。但是,上面的代碼拋出了一個鑄造錯誤。 List<AbstractDType>無法轉換爲List<PD1>。如何修復這個錯誤,以便我可以在GetData方法中返回具體值。

有從DTypeStrategy繼承其他派生類這將是實現的GetData(),如如下:(我假設我會在這裏得到同樣的錯誤鑄件以及)

public class MyDraw : DTypeStrategy 
{ 
    public override List<AbstractDType> GetData() 
    { 
      return new List <AD2>(); 
    } 
} 

回答

0

會從您發佈的代碼中看來,在繼承DTypeStrategy時,您知道要返回哪個具體類。

因此你可以把DTypeStrategy成一個通用類

public abstract class DTypeStrategy <T> where T:AbstractDType 
{ 
    protected abstract List<T> GetData(); 
} 

,然後這個工程:

public class MyDraw : DTypeStrategy <AD2> 
{ 
    public override List<AD2> GetData() 
    { 
      return new List <AD2>(); 
    } 
} 
1

什麼是這裏您的實際目標是什麼?如果你真的只是想從的GetData返回一個列表,包含 AD1,你可以這樣做:

protected virtual List<AbstractDType> GetData() 
{ 
     var stuff = new List<AbstractDType>(); 
     stuff.Add(new AD1()); 
     return stuff; 
} 

但如果你真的想返回的具體類型的列表,然後,嗯,你可以」這樣做 - 它指出了你的設計中的一個缺陷。想調用代碼的,如果這是可能的

public void Victim(DTypeStrategy strat) 
{ 
    List<AbstractDType> list = strat.GetData(); 
    //oops, the list is actually a list<AD1>, so this throws: 
    list.Add(new AD2()); 
} 

問自己:

  • 我爲什麼要返回一個專門的列表,而不是AbstractDType之一?
  • 爲什麼它應該是一個List,而不是IEnumerable?

如果你必須有某種原因,一個專門的列表,使用一般方法:

public class DTypeStrategy<T> where T: AbstractDType 
{ 
    //not sure a concrete here is a good idea, but you get the point... 
    public virtual List<T> GetData() 
    { 
     return new List<T>(); 
    } 
} 

public class MyDraw : DTypeStrategy<AD2> 
{ 
    public override List<AD2> GetData() 
    { 
     return new List<AD2>(); 
    } 
} 

如果您不需要List<T>,那麼你可能濫用的C#的covariant generic interfaces做到這一點 - 但再次,我會看看你的設計第一

+0

我正在使用策略模式來創建基於typeID的具體對象。每個具體對象的GetData()方法都會返回一個特定的列表,如AD1,AD2或AD3的列表。從AbstractDType繼承的AD1,AD2和AD3。 DTypeStrategy將具有默認行爲的GetData()方法。 – 2011-05-09 12:05:47

+0

@Alan B在戰略模式中,調用策略的代碼不需要知道具體的List GetData是什麼返回的,所以最上面的代碼片段就是你想要的 - 從抽象中創建列表並添加實例它的子類。 – 2011-05-09 19:30:10