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

时间:2019-05-22 17:06:35

标签: c# .net clr gac-msil

如下面的代码所示,在两个不同的程序集中定义了两个接口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错误地具有相同的签名(程序集弱名或强名)。为Bar类生成的MSIL是否会根据在构建期间使用的是程序集A还是程序集而有所不同?

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

1 个答案:

答案 0 :(得分:1)

接口映射是在构建时创建的,并且如果在构建时使用的{Assembly A”(一种方法)比Foo类仅在其接口映射中映射一种方法。

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

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

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

正如汉斯·帕森(Hans Passant)所指出的那样,C#8引入了default interface methods来解决这个确切的问题。