【问题标题】:Is there any way to create a public .NET interface which can't be implemented outside of it's assembly?有没有办法创建一个无法在其程序集之外实现的公共 .NET 接口?
【发布时间】:2014-11-11 19:04:34
【问题描述】:

为了在 .NET 中保持二进制向后兼容性,通常不能向公共类和接口添加新的抽象方法。如果这样做,那么针对扩展/实现您的类/接口的旧版本程序集构建的代码将在运行时失败,因为它无法完全扩展/实现新版本。然而,对于类,有一个方便的解决方法:

public abstract class Foo {
    internal Foo() { }
}

因为 Foo 的构造函数是内部的,所以我的程序集之外的任何人都不能扩展 Foo。因此,我可以向 Foo 添加新的抽象方法而不必担心向后兼容性,因为我知道另一个程序集中的任何类都不能扩展 Foo。

我的问题是,接口是否有类似的技巧?我可以创建一个公共接口并以某种方式保证我的程序集之外的任何人都无法创建它的实现吗?

【问题讨论】:

    标签: c# interface abstract backwards-compatibility


    【解决方案1】:

    不,你不能那样做。但是,考虑到接口的意义在于通过定义契约来定义实现的行为,这是有道理的。

    但是,您可以做的是创建一个继承自您的 public interfaceinternal interface

    public interface IPublicInterface {
        /* set-in-stone method definitions here */
    }
    
    internal interface IChildInterface : IPublicInterface  {
        /* add away! */
    }
    

    这应该可以防止与其他程序集的任何向后兼容性问题,同时仍然允许您隐藏其他方法。

    当然,缺点是您必须记住在需要时将其转换为 IChildInterface,而不是简单地将其用作 IPublicInterface

    不过,老实说,如果您真的想定义一些仅用于汇编的功能,同时仍要求最终用户为某些方法定义自己的实现,那么您最好的选择可能是抽象类。

    【讨论】:

    • 这样不会让他类的用户看到子接口新增的方法。实际上,它为 OP“冻结”IPublicInterface,就像发布任何接口一样。
    • 对,也许我误读了这个问题。 OP 询问“我可以创建一个公共接口并以某种方式保证我的程序集之外的任何人都无法创建它的实现吗?”对我来说,这意味着隐藏它,特别是因为 OP 给出的示例处理了内部构造函数,这些构造函数也对用户隐藏。由于接口没有固有的功能,因此在外部定义的实现上调用内部方法是不可能的。不过,只要方法不是抽象的,这将适用于抽象类。
    【解决方案2】:

    不,你不能。

    但由于在 IL 中接口本质上只是一个纯抽象类(即根本没有任何实现的类),因此您可以使用您已经描述的技术,并且实际上是相同的。

    如前所述,请记住,这种方法确实将您的类型限制为仅继承虚假的“抽象类”接口。它可以实现其他接口,但不能继承任何其他类型。这可能是也可能不是问题,具体取决于场景。

    如果它让您对设计感觉更好,请按照 .NET 接口约定命名您的纯抽象类。例如。 IFoo 而不是 Foo

    当然,它确实暗示了一个问题:您为什么要这样做?如果您根本没有实现,那么允许其他代码实现您的接口会带来什么危害?

    但从实际的角度来看,可以按照您想要的方式执行您的规则。

    【讨论】:

    • 将你的类基于一个纯抽象类会带走扩展你选择的另一个类的可能性,所以 class MyClass : MyBase, IFoo 基于 IFoo 的名称看起来像一个有效的东西将变得非法,除非IFoo其实是一个接口。
    • 是的,没错。这是否是相关限制取决于具体情况。不过,在答案中值得一提。
    • @PeterDuniho 这是否意味着您可以在原始 IL 中定义这样的接口?
    猜你喜欢
    • 1970-01-01
    • 2019-03-09
    • 2011-02-14
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    相关资源
    最近更新 更多