Answers:
有关该主题的MSDN文章是“ 通过密封类限制可扩展性”。
类应该设计为继承或禁止继承。设计继承需要付出代价:
关于有效Java的条款17对此进行了更详细的介绍-无论它是在Java上下文中编写的,该建议也适用于.NET。
我个人希望在.NET中默认密封类。
自从大约9年前提出此问题以来,微软官方的密封指南似乎已经发展起来,并且从选择加入的哲学(默认为密封)变为选择退出(默认为不密封):
X不要在没有充分理由的情况下密封课程。
因为您无法考虑可扩展性场景而封闭类并不是一个很好的理由。框架用户喜欢出于各种非显而易见的原因而从类继承,例如添加便利成员。有关用户要从类型继承的非显而易见原因的示例,请参见未密封类。
密封课程的充分理由如下:
- 该类是静态类。请参见静态类设计。
- 该类将安全敏感的机密存储在继承的受保护成员中。
- 该类继承了许多虚拟成员,单独密封它们的成本将超过使该类不密封的好处。
- 该类是需要非常快速的运行时查找的属性。密封属性的性能水平比未密封属性高。请参阅属性。
X请勿在密封类型上声明受保护的成员或虚拟成员。
根据定义,密封类型不能继承。这意味着不能调用密封类型上的受保护成员,并且不能覆盖密封类型上的虚拟方法。
✓考虑您要覆盖的密封件。引入虚拟成员(在虚拟成员中讨论)可能导致的问题也适用于替代,尽管程度较小。从继承层次结构中的这一点开始,密封替代将使您免受这些问题的困扰。
的确,如果您搜索ASP.Net Core代码库,则只会发现约30种情况sealed class
,其中大多数是属性和测试类。
我确实认为,不变性守恒是支持密封的一个很好的论据。
性能是一个重要因素,例如,java中的字符串类是final(<-密封),其原因仅是性能。我认为另一个重要的点是避免在此处详细描述的脆弱的基类问题:http : //blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes。 aspx
如果提供框架,那么对于遗留项目的可维护性以及升级框架以避免脆弱的基类问题非常重要。
String
该类甚至可能不是子类,即使它不是最终的。
进一步的考虑是,密封类不能在单元测试中存根。从Microsoft的文档中:
密封类或静态方法不能存根,因为存根类型依赖于虚拟方法分派。对于这种情况,请使用使用垫片中所述的垫片类型将应用程序与其他程序集隔离以进行单元测试