1

如下代码所示,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 错误地具有相同的签名(程序集弱名称或强名称)。为类生成的 MSILBar是否会根据构建时使用的是程序集 A 还是程序集而有所不同?

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

4

1 回答 1

1

接口映射是在构建时创建的,如果在构建时使用“程序集 A”(1 个方法),Foo则类将仅在其接口映射中映射一个方法。

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

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

如果预计这是常见问题,您可以考虑使用方法的默认实现从“程序集 A”公开基类,以允许将方法添加到接口并Foo从该类而不是接口派生您的方法。

正如 Hans Passant 指出的那样,C# 8 引入了默认接口方法来解决这个确切的问题。

于 2019-05-22T17:48:16.947 回答