为什么要盖一个class?
我想听听.Net框架中大量密封类的动机是什么。 封盖课程有什么好处? 我无法理解如何让inheritance可以是有用的,而且很可能不是唯一一个与这些阶级作战的人。
那么,为什么这个框架是以这种方式devise的呢?为什么要开封一切呢? 必须有另一个原因,但只是邪恶?
- 有时候课程太珍贵了,并不是为了inheritance而devise的。
- 在查找types时,运行时/reflection可以对密封类进行inheritance假设。 一个很好的例子是 – 为了查找运行时速度,build议使用属性进行密封。 如果MyAttribute是密封的,则type.GetCustomAttributes(typeof(MyAttribute))将执行得更快。
本主题的MSDN文章是通过密封类限制可扩展性 。
类应该被devise为inheritance或者禁止它。 deviseinheritance需要花费一些代价:
- 它可以固定你的实现(你必须声明哪些方法将调用哪些其他方法,以防用户覆盖一个而不是另一个)
- 它揭示了你的实现,而不仅仅是效果
- 这意味着在devise时你必须考虑更多的可能性
- 像Equals这样的东西很难在inheritance树中devise
- 它需要更多的文档
- 被分类的不可变types可能变得可变(ick)
有效Java的第17项详细介绍了这一点 – 无论它是否在Java语境中编写,这个build议也适用于.NET。
我个人希望在.NET中默认封闭类。
我在msdn文档中发现了这样一句话:“密封类主要用于防止派生,因为它们永远不能用作基类,所以一些运行时优化可以使密封类成员的调用稍微快一点。
我不知道是否表演是封闭课程的唯一优势,我个人还想知道其他原因。
性能是一个重要的因素,例如,java中的string类是final(< – sealed),原因仅仅是性能。 我认为另一个重要的一点是要避免这里详细描述的脆弱的基类问题: http : //blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes。 ASPX
如果您提供了一个框架,那么对于可维护性遗留项目以及升级您的框架来避免脆弱的基类问题是非常重要的
看起来,自从9年前问这个问题以来, 微软关于密封的正式指导方针已经发展了,并且他们从一个selectjoin原则(默认密封)转到select退出(默认情况下不encryption):
X不要在没有充分理由的情况下封印课程。
密封一个类,因为你不能想到一个可扩展性的情况是不是一个好的理由。 框架用户喜欢从各种非显而易见的原因inheritance类,如添加便利的成员。 有关用户希望从typesinheritance的非明显原因的示例,请参阅“未密封类”。
密封课程的理由包括以下几点:
- 该类是一个静态类。 请参阅静态类devise。
- 该类将安全敏感的秘密存储在inheritance的受保护成员中。
- 这个class级inheritance了许多虚拟成员,单独封闭他们的成本将超过离开class级的好处。
- 该类是一个需要非常快的运行时查找的属性。 密封的属性比未密封的属性略高一些。 请参阅属性。
X请勿在密封types上声明受保护或虚拟成员。
根据定义,密封的types不能被inheritance。 这意味着密封types的受保护成员不能被调用,并且密封types的虚拟方法不能被覆盖。
✓考虑你重写的密封成员。 引入虚拟成员(在虚拟成员中讨论)可能导致的问题也适用于覆盖,尽pipe程度稍低。 密封覆盖屏蔽你从inheritance层次结构中的这一点开始的这些问题。
事实上,如果你searchASP.Net核心代码库 ,你只会发现大约30个sealed class
,其中大部分是属性和testing类。
我认为不变性保护是一个有利于密封的好理由。
密封是用来防止“脆弱的基类问题”。 我在MSDN中find了一篇很好的文章来解释这一点。
密封允许您实现一些小的性能收益。 在JIT和懒惰的悲观世界中,这比在C ++这个世界中更不那么真实,但是由于.NET不如Java编译器那么好,因为Java编译器主要是因为不同的devise哲学,它仍然是有用的。 它告诉编译器它可以直接调用任何虚拟方法,而不是通过vtable间接调用它们。
当你想要一个像“平等比较”这样的“封闭世界”时,这一点也很重要。 通常情况下,一旦我定义了一个虚拟方法,我就非常容易定义一个真正实现这个想法的平等比较的概念。 另一方面,我可以使用虚方法为类的特定子类定义它。 密封这个课程确保了平等。
封闭一个类可以简化pipe理一次性资源。
- 寻找沙盒.NET插件的实用方法
- 为什么在定义事件时需要“事件”关键字?
- DataGridView.Clear()
- 在结构上使用“新”是否将它分配到堆或栈上?
- 什么是IndexOutOfRangeException / ArgumentOutOfRangeException,如何解决?
- .NET的`Array.Sort()`方法使用的sortingalgorithm是一个稳定的algorithm吗?
- 我如何使用DateTime指定一天的最新时间?
- AppSettings vs applicationSettings的优缺点(.NET app.config / Web.config)
- 在C#中,new object()和new {}有什么区别?