为了保持.NET 中的二进制向后兼容性,通常不能向公共类和接口添加新的抽象方法。如果这样做,那么针对扩展/实现类/接口的旧版本程序集构建的代码将在运行时失败,因为它无法完全扩展/实现新版本。然而,对于课程,有一个方便的解决方法:
public abstract class Foo {
internal Foo() { }
}
因为 Foo 的构造函数是内部的,所以我的程序集之外的任何人都无法扩展 Foo。因此,我可以向 Foo 添加新的抽象方法,而不必担心向后兼容性,因为我知道另一个程序集中没有类可以扩展 Foo。
我的问题是,接口有类似的技巧吗?我可以创建一个公共接口并以某种方式保证我的程序集之外的任何人都无法创建它的实现吗?
不,你不能那样做。但是,考虑到接口的要点是通过定义契约来定义实现的行为,这是有道理的。
但是,您可以做的是创建一个继承自您的
internal interface
的 public interface
:
public interface IPublicInterface {
/* set-in-stone method definitions here */
}
internal interface IChildInterface : IPublicInterface {
/* add away! */
}
这应该可以防止与其他程序集出现任何向后兼容性问题,同时仍然允许您隐藏其他方法。
当然,缺点是您必须记住在需要时将其转换为
IChildInterface
,而不是简单地将其用作 IPublicInterface
老实说,如果您确实想定义一些仅限程序集的功能,同时仍然要求最终用户为某些方法定义自己的实现,那么您最好的选择可能是抽象类。
不,你不能。
但是,由于在 IL 中,接口本质上只是一个纯抽象类(即根本没有任何实现),因此您可以使用已经描述过的技术,并且它实际上是相同的。
如前所述,请记住,这种方法确实将您的类型限制为仅继承伪造的“抽象类”接口。它可以实现其他接口,但无法继承任何其他类型。这可能是也可能不是问题,具体取决于具体情况。
如果这让您对设计感觉更好,请按照 .NET 接口约定命名您的纯抽象类。例如。
IFoo
而不是Foo
。
当然,这确实暗示了一个问题:为什么要这样做?如果您根本没有实现,那么允许其他代码实现您的接口会带来什么危害?
但从实际角度来看,可以按照您想要的方式执行您的规则。
c# 8.0之后,可以使用internal关键字:
public interface IA
{
internal void OnlyImplementableInternal();
}