当我实现基类也实现的接口时,为什么不收到编译器警告?

sco*_*obi 4 c# inheritance interface

在下面的代码中,我正在实现一个接口,然后从该类派生并实现相同的接口.当我处理派生类的实例时,它只调用派生的实现.

为什么C#编译器不会对此发出警告?由于几个原因,这似乎很危险.我可以实现一个基础实现的接口,这将给我一些我没想到的行为(比如基地不再处理).或者如果我后来决定让一个基础实现一个新的接口,我必须扫描所有代码以找到可能已经实现它的任何衍生物.

对于派生类中的重复成员,编译器要求我们使用"覆盖"或"新".

为什么接口不同?

class CA : IDisposable
{
    void IDisposable.Dispose() { Debug.WriteLine("CA.Dispose"); }
}

class CB : CA, IDisposable
{
    void IDisposable.Dispose() { Debug.WriteLine("CB.Dispose"); }
}

class Program
{
    static void Main(string[] args)
    {
        using (new CB()) { }
    }
}

// output: CB.Dispose
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 6

它只是这样做,因为你正在使用显式接口实现.例如,这不编译:

using System;
using System.Diagnostics;

class CA : IDisposable
{
    public void Dispose()
    {
        Debug.WriteLine("CA.Dispose");
    }
}

class CB : CA, IDisposable
{
    public void Dispose()
    {
        Debug.WriteLine("CB.Dispose");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,是的,你需要小心显式接口实现.情况总是这样,因为无论如何,它在类型系统方面有点奇怪.

这并不理想,但显式接口实现是有部分是为了得到你圆难堪的局面,希望能够重新实现一个接口.

老实说,如果你在最后阶段决定一个基类应该开始实施IDisposable,那么无论如何你都处于一个受伤的世界 - 因为你必须检查你正在使用该类的每一个地方,以便判断是否或不是你需要一份using声明.

  • @Scott:我认为你的观点是隐式接口重新实现而没有"新"导致一种脆弱的基类问题; 基类中的意外更改可能导致派生类具有意外的不良行为.警告如果方法中缺少"new",则旨在减轻虚拟方法的失败.通过类比,我们可以在接口重新实现上要求相同的.我没有考虑过这么多,但是,乍一看,这似乎是一个初步设计本来可以更好的领域.尽管如此,这将是一个令人讨厌的突破性变化. (4认同)