【发布时间】:2010-09-21 01:28:08
【问题描述】:
我想知道 .Net 框架中大量密封类背后的动机是什么。密封类有什么好处?我无法理解不允许继承如何有用,而且很可能不是唯一一个与这些类作斗争的人。
那么,为什么要这样设计框架,而解封所有内容不是不可改变的变化吗?除了邪恶之外,肯定还有别的原因吧?
【问题讨论】:
标签: .net performance
我想知道 .Net 框架中大量密封类背后的动机是什么。密封类有什么好处?我无法理解不允许继承如何有用,而且很可能不是唯一一个与这些类作斗争的人。
那么,为什么要这样设计框架,而解封所有内容不是不可改变的变化吗?除了邪恶之外,肯定还有别的原因吧?
【问题讨论】:
标签: .net performance
类应该设计成继承或禁止继承。设计继承是有代价的:
Effective Java 的第 17 项对此进行了更详细的介绍 - 不管它是在 Java 上下文中编写的,但该建议也适用于 .NET。
我个人希望类在 .NET 中默认密封。
【讨论】:
此主题的 MSDN 文章是 Limiting Extensibility by Sealing Classes。
【讨论】:
似乎official Microsoft guidelines on sealing 自从大约 9 年前提出这个问题以来已经发展,他们从选择加入哲学(默认密封)转变为选择退出(默认不密封):
X 不要在没有充分理由的情况下密封课程。
密封类,因为您无法想到可扩展性场景 不是很好的理由。框架用户喜欢从类继承 各种不明显的原因,例如添加便利成员。看 Unsealed Classes 用于用户想要的非显而易见原因的示例 从类型继承。
封闭课程的充分理由包括:
- 该类是静态类。请参阅静态类设计。
- 该类将安全敏感的机密存储在继承的受保护成员中。
- 该类继承了许多虚拟成员以及密封它们的成本 个人会超过离开班级的好处 开封。
- 类是一个属性,需要非常快的运行时间 抬头。密封属性的性能水平略高 比未密封的。请参阅属性。
X DO NOT在密封类型上声明受保护或虚拟成员。
根据定义,密封类型不能被继承。这意味着 不能调用密封类型上的受保护成员,并且虚拟 密封类型的方法不能被覆盖。
✓ 考虑您覆盖的密封成员。引入虚拟会员可能导致的问题(在虚拟会员中讨论) 也适用于覆盖,尽管程度略低。 从那开始,密封一个覆盖可以保护您免受这些问题的影响 继承层次结构中的点。
确实,如果你search the ASP.Net Core codebase,你只会发现sealed class的出现大约30个,其中大部分是属性和测试类。
我确实认为不变性守恒是支持密封的一个很好的论据。
【讨论】:
我在 msdn 文档中找到了这句话:“密封类主要用于防止派生。因为它们永远不能用作基类,所以一些运行时优化可以使调用密封类成员的速度稍快一些。”
我不知道性能是否是密封类的唯一优势,我个人也想知道其他任何原因......
【讨论】:
性能是一个重要因素,例如,java 中的字符串类是 final(http://blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes.aspx
如果你提供一个框架,那么对于遗留项目的可维护性和升级你的框架以避免脆弱的基类问题很重要
【讨论】:
String 类甚至可能无法子类化,即使它不是最终的。
Sealed 用于防止“脆弱的基类问题”。我在 MSDN 中找到了一个 good article 来解释这一点。
【讨论】:
密封允许您实现一些小的性能提升。这在 JIT 和惰性悲观化的世界中不如在 C++ 的世界中那么正确,但由于 .NET 不如 Java 编译器的悲观化那么好,主要是因为不同的设计理念,它仍然有用。它告诉编译器它可以直接调用任何虚方法,而不是通过vtable间接调用它们。
当您想要一个“封闭世界”来进行平等比较等事情时,这一点也很重要。通常,一旦我定义了一个虚拟方法,我就会非常想定义一个真正实现这个想法的相等比较的概念。另一方面,我也许可以使用虚拟方法为类的特定子类定义它。密封该类可确保平等确实成立。
【讨论】:
密封类可以更轻松地管理一次性资源。
【讨论】:
判断是否封装类、方法或属性,一般要考虑以下两点:
•通过自定义类的能力,派生类可能获得的潜在好处。
•派生类可能会修改您的类,使其不再正常工作或无法按预期工作。
【讨论】:
进一步的考虑是密封类不能在您的单元测试中存根。来自Microsoft's documentation:
不能对密封类或静态方法进行存根,因为存根类型依赖于虚拟方法分派。对于这种情况,请使用 shim 类型,如使用 shim 将您的应用程序与其他程序集隔离以进行单元测试中所述
【讨论】: