返回一个抽象类列表

时间:2011-05-09 11:37:15

标签: c#

  

可能重复:
  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>();  
   }    
}

我想在GetData()方法中返回PD1(具体类型)的列表。但是上面的代码引发了一个转换错误。 List<AbstractDType>无法转换为List<PD1>。如何修复此错误,以便我可以在GetData方法中返回具体内容。

还有其他从DTypeStrategy继承的派生类,它们将实现GetData(),如下所示:(我假设我在这里也会得到相同的转换错误)

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

2 个答案:

答案 0 :(得分: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来执行此操作 - 但同样,我会首先查看您的设计

答案 1 :(得分: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>();  
   } 
}