实现接口与添加新方法之间有区别吗?

Is there a difference between implementing an interface vs adding a new method?

如下面的代码所示,在两个不同的程序集中定义了两个接口IFoo

/// assembly A
interface IFoo {
    void DoSomething()
}

/// assembly B
interface IFoo {
    void DoSomething()

    void DoSomethingElse()
}

/// assembly C
class Bar : IFoo {
    public virtual void DoSomething()

    public virtual void DoSomethingElse()
}

假设程序集 A 和程序集 B 错误地具有相同的签名(程序集弱名称或强名称)。为 class Bar 生成的 MSIL 是否会有所不同,具体取决于在构建期间使用的是程序集 A 还是程序集?

换句话说,假设我们在 运行 时用程序集 A 和 C 构建一个项目,在 运行 时用程序集 B 替换 A 是否可以?或者我会得到类似 "IFoo.DoSomethingElse" 未实现的异常,因为在构建过程中 DoSomethingElse 被认为是一种新方法,而不是在接口中实现现有方法。

接口映射是在构建时创建的,如果 "assembly A"(1 种方法)在构建时使用,那么 Foo class 只会在其接口映射中映射一种方法。

创建 class 的实例时,它将尝试使用在 运行 时可用的接口(这不一定与编译时使用的接口相同,如您的情况)并将无法映射新的第二种方法。

在 C# 8 之前确实没有解决它的好方法 - 您要么必须降级依赖项以使其接口向后兼容,要么使用新版本的依赖项重新编译您的代码。

如果预计这是一个常见问题,您可以考虑使用方法的默认实现从 "assembly A" 公开基础 class,以允许添加接口方法并从中派生 Foo class 而不是界面。

正如 Hans Passant 指出的那样,C# 8 引入了 default interface methods 来解决那个确切的问题。