我有一个例子,我希望抽象类接口返回类似这样的东西
abstract class AnimalProcessor {
public abstract IList<Animal> ProcessResults();
}
然后是具体的例子
class GiraffeProcessor : AnimalProcessor {
public override IList<Animal> ProcessResults() {
return new List<Giraffe>();
}
}
class LionProcessor : AnimalProcessor {
public override IList<Animal> ProcessResults() {
return new List<Lion>();
}
}
问题是具体类需要具有相同的签名才能覆盖ProcessResults()
方法,因此需要返回IList<Animal>
,但是我要返回的ACTUAL数据是{{1 },IList<Lion>
等,但调用代码必须执行
IList<Giraffe>
哪个不给我一个我想要的Ilist。
问题
1)以上代码无法编译。 giraffeProcessor必须返回一个具体的GiraffeProcessor processor = new GiraffeProcessor();
IList<Animal> results = processor.GetResults();
,你可以用List<Animal>
个对象填充它,但你要构造的对象类型必须是Giraffe
。不理想。
2)当您返回结果时,您只能获得List<Animal>
,而不是IList<Animal>
。我已经尝试明确地向IList<Giraffe>
投射
IList<Giraffe>
这会产生运行时错误,可能是因为返回的对象不是IList<Giraffe> results = (IList<Giraffe>) processor.GetResults();
,而是IList<Giraffe>
CONTAINS IList<Animal>
个对象。
任何人都可以通过我的设计向我提出错误的建议,因为我有点难以实现这一目标。
答案 0 :(得分:6)
怎么样:
abstract class AnimalProcessor<T> where T : Animal {
public abstract IList<T> ProcessResults();
}
class GiraffeProcessor : AnimalProcessor<Giraffe> {
public override IList<Giraffe> ProcessResults() {
return new List<Giraffe>();
}
}
class LionProcessor : AnimalProcessor<Lion> {
public override IList<Lion> ProcessResults() {
return new List<Lion>();
}
}
答案 1 :(得分:1)
您可以通过使用泛型类型约束声明AnimalProcessor来解决此问题,例如:
public abstract class AnimalProcessor<T> where T : Animal
{
public abstract IList<T> ProcessResults();
}
如果不起作用,可以使用LINQ Cast运算符,例如:
public class GiraffeProcessor : AnimalProcessor
{
public override IList<Animal> ProcessResults()
{
return new List<Giraffe>().Cast<Animal>();
}
}
或者,将列表内部存储为Animal,但将Giraffe添加到其中,例如
public class GiraffeProcessor : AnimalProcessor
{
private List<Giraffe> _innerList = new List<Giraffe>();
public override IList<Animal> ProcessResults()
{
return new List<Animal>(innerList ); }
}
致以最诚挚的问候,
答案 2 :(得分:1)
如果您使用的是C#4.0,则可以问自己处理器是应该返回IEnumerable<T>
而不是IList<T>
。如果答案是肯定的,那么你可以从协方差中获益:
abstract class AnimalProcessor {
public abstract IEnumerable<Animal> ProcessResults();
}
class GiraffeProcessor : AnimalProcessor {
public override IEnumerable<Animal> ProcessResults() {
return new List<Giraffe>();
}
}
class LionProcessor : AnimalProcessor {
public override IEnumerable<Animal> ProcessResults() {
return new List<Lion>();
}
}
这里有几个优势。首先,您可以将它们实现为迭代器块:
class GiraffeProcessor : AnimalProcessor {
public override IEnumerable<Animal> ProcessResults() {
yield break;
}
}
其次,不那么简单,您允许客户端代码决定将动物转移到哪种集合中 - 如果有的话。例如,请考虑消费者可能需要LinkedList<Animal>
:
var animals = new LinkedList<Animal>(animalProcessor.ProcessResults());
或者考虑客户端可能只需要迭代序列:
foreach (var animal in animalProcessor.ProcessResults())
{ /*... do something ...*/ }
在任何一种情况下,如果您在ProcessResults中使用ToList()
调用,那么您将无需创建列表。如果消费者真的想要List<Animal>
,那么这很容易实现:
var animals = new List<Animal>(animalProcessor.ProcessResults());
最后,即使您更改了方法返回值的接口类型,您也可以从通用方法中受益:
abstract class AnimalProcessor<T> where T : Animal {
public abstract IEnumerable<T> ProcessResults();
}
class GiraffeProcessor : AnimalProcessor<Giraffe> {
public override IEnumerable<Giraffe> ProcessResults() {
yield break;
}
}
class LionProcessor : AnimalProcessor<Lion> {
public override IEnumerable<Lion> ProcessResults() {
return Enumerable.Empty<Lion>();
}
}