接口继承和属性隐藏问题

9

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

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输出是合理的,但我无法接受最后一个输出,即使使用Base类型的临时变量,它仍然输出Child。有人能解释这里发生了什么吗?
更新
通过移除接口IChild((child as Base) as IBase).Text突然结果为"Base"。这让我得出结论,只要Child实现IBase(直接或通过接口继承),结果将是"Child"而不是"Base"
当你重构一个在其他类中以IBase作为参数而不是Base的方法时,这可能会变得非常棘手,因为它会导致不同的行为。

4
当然,你应该避免这个混乱。需要“新”的成员从来不是好兆头。 - H H
实际上,那个 new 属性是死代码并引发了异常。它从未被使用,因为代码始终使用基础类型。添加基础接口使得那段死代码可以复活 :) - huysentruitw
1个回答

9
基本上你在这里进行的是类型转换:
(child as Base) 转换为 Base 并且你使用了 Base 的 Text 字段。很清楚。
但是在这里:
(child as Base) as IBase 你将 Child 转换为 Base,然后再转换为 IBase,这意味着你将 Child 转换为 IBase,这意味着 Child 的 Text 将被显示出来。你没有使用 as 改变基础对象的类型。
因此,这里的 (child as Base) as IBase 和 child as IBase 是相同的。
编辑:
编辑后的问题并没有改变这个答案是正确的事实。正如 @InBetween 所说,它只是改变了 Text 属性的实现方式。所以,Child 类不再直接实现 IBase,因此现在会使用 Base 的 Text 作为最佳匹配。基本上,它只是使用第一个实现 IBase 的类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接