List <interfaceimplementation>与List <baseclassextension>

时间:2018-09-20 14:45:03

标签: c# .net

我有一个接口(IFoo)和另一个包含List<IFoo>的接口(IBar),我的目标是实现IFoo(FooImp)并将其用于IBar(BarImp)的实现中。我知道接口不会传递属性,并且您应该使用抽象基类,但是我无法弄清楚如何实现此目的。这是我无法使用的接口和实现,但是我以此为起点:

public interface IFoo
{
    bool BoolOne { get; set; }
}

public interface IBar
{
    List<IFoo> FooList { get; }
}

/// <summary> Implements IFoo interface </summary>
public class FooImp : IFoo
{
    public bool BoolOne { get; set; } //required interface implementation
    public bool BoolTwo { get; set; } //new property
}

/// <summary>Implements IBar interface </summary>
public class BarImp : IBar //Error - does not implement
{
    public List<FooImp> FooList { get; private set; } //Error: "Does not match the expected type 'IFoo'". No suprise here
}

接下来,我将接口转换为抽象库(FooBase和BarBase)并扩展了它们(FooExt和BarExt):

public abstract class FooBase
{
    public abstract bool BoolOne { get; set; }
}

public abstract class BarBase
{
    public abstract List<FooBase> FooList { get; protected set; }
}

public class FooExt : FooBase
{
    public override bool BoolOne { get; set; } //implement abstract property

    public bool BoolTwo { get; set; } //add new property
}

 public class BarExt : BarBase //Error: FooList<FooBase> not implemented
{        
    public override List<FooExt> FooList { get; protected set; }      //Error: "Type must be FooBase"
}

我不明白为什么最后一行"Type must be FooBase"上有错误。我以为FooExt是一个多态的FooBase。

我尝试了Linq ConvertAll()overrridenew的很多(在此处列出所有内容)组合,并通过构造函数和其他函数传递值,但找不到任何会编译。我应该使用其他设计模式吗?

这不是this的副本,因为我的列表容器是一个接口。这些答案是有帮助的,但对于这个问题是非常正确的。

2 个答案:

答案 0 :(得分:1)

通过覆盖,您无法更改成员签名。

假设您的程序用户获得了BarBase的实例,例如从服务器或任何东西。

class MyServer
{
    public BarBase GetBar() { ... }
}

var bar = server.GetBar();

该用户应该如何知道此实例FooList-属性实际上包含FooExt的实例?不能这样,因为BarBase提供的 contract 仅声明了List<FooBase>

如果我们能够做到这一点,我们还可以将AnotherFoo的实例添加到该列表中,该实例也继承自FooBase

bar.FooList.Add(new AnotherBar())

现在您的FooList将包含FooExt-和AnotherBar实例。

因此,覆盖时,您必须使用与覆盖成员完全相同的签名。

答案 1 :(得分:1)

在覆盖的方法中,您更改了type参数。您不能这样做,因为它会使签名不同。

您可以做的是使用泛型:

public abstract class Base<T> where T : FooBase
{
    public abstract List<T> FooList { get; protected set; }
}

然后您可以像这样覆盖它:

public class Ext : Base<FooExt>
{        
    public override List<FooExt> FooList { get; protected set; }
}