Return an abstract class list

Possible duplicate:
Cast List <T> - The problem of covariance / contravariance

I have classes defined below

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

I would like to return a list of PD1 (specific type) in the GetData () method. However, the above code generated a casting error. List<AbstractDType> cannot be converted to List<PD1> . How to fix this error so that I can return a specific GetData method.

There are other derived classes inherited from DTypeStrategy that will implement GetData (), for example, below: (I assume that I will also get the same casting error)

 public class MyDraw : DTypeStrategy { public override List<AbstractDType> GetData() { return new List <AD2>(); } } 
+7
source share
2 answers

What is your actual goal? If you really want to return a list from GetData that contains AD1, you can do this:

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

But if you really want to return a list of a specific type, then, well, you cannot do this - and this indicates a flaw in your design. Remember the call code, if possible:

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

Ask yourself:

  • Why do I want to return a custom list, and not one from AbstractDType?
  • Why should it be a list at all, and not IEnumerable?

If you MUST have a custom list for any reason, use the general method:

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

If you don't need a List<T> , you may possibly abuse C # covariant generic interfaces to do this - but then again, I look at your design first.

+1
source

It would seem that from the code you posted, by the time you inherit DTypeStrategy , you know which specific class you want to return.

So you can turn DTypeStrategy into a generic class

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

and then it works:

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

All Articles