接口继承和属性隐藏问题

时间:2015-11-13 12:11:50

标签: c# inheritance interface

我最近在基类上引入了一个用于单元测试目的的接口,并遇到了一个奇怪的问题。这是可重现性最小的方案:

interface IBase
{
    string Text { get; }
}

interface IChild : IBase
{
}

class Base : IBase
{
    public string Text { get { return "Base"; }}
}

class Child : Base, IChild
{
    public new string Text { get { return "Child"; }}
}

static void Main(string[] args)
{
    var child = new Child();
    Console.WriteLine(child.Text); // Outputs "Child"
    Console.WriteLine((child as Base).Text); // Outputs "Base"
    Console.WriteLine(((child as Base) as IBase).Text); // Outputs "Child"
}

前两个Console.WriteLine命令的输出是逻辑的,但是我无法接受最后一个的输出,当使用Child类型的临时变量时它甚至输出Base 。谁能解释一下这里发生了什么?

更新

通过删除界面IChild((child as Base) as IBase).Text突然导致"Base"。这使我得出结论,只要Child实现IBase(直接或通过接口继承),结果将是"Child"而不是"Base"

当你在另一个类中重构一个方法来取一个IBase而不是Base的参数时,这会变得非常棘手,因为它会突然导致不同的行为。

1 个答案:

答案 0 :(得分:9)

基本上你在这里施展:

(child as Base)Base,您正在使用Base的{​​{1}}字段。很明显。

但是在这里:

Text您将(child as Base) as IBase投放到Child,然后投放到Base,这意味着您将IBase投射到Child,这意味着{将显示{1}}的{​​{1}}。您没有使用IBase更改基础对象。

因此ChildText相同。

编辑:

编辑的问题不会改变这个答案是正确的事实。正如@InBetween所说,它只是改变了as属性的实现解决方式。因此(child as Base) as IBase类不再直接实现child as IBase,因此现在Text的{​​{1}}将被用作最佳匹配。基本上它只是使用第一类实现Child