为什么';密封的';关键字是否存在于.Net中?

为什么';密封的';关键字是否存在于.Net中?,.net,keyword,sealed,.net,Keyword,Sealed,.Net framework中的大量类被标记为“密封”,阻止您用自己的类继承这些类。当然,这违背了面向对象的本质,在面向对象中,可以扩展和重新定义现有对象的行为 “sealed”关键字的存在是否有充分的理由 例如,, 中的NotifyCollectionChangedEventArgs Silverlight是密封的。我想 创建我自己的版本 支持 添加范围和删除范围,但 Silverlight版本的NCCEA没有 提供一个支持 新项目和新项目的多个项目 OldItems属性,已定义为ILists

.Net framework中的大量类被标记为“密封”,阻止您用自己的类继承这些类。当然,这违背了面向对象的本质,在面向对象中,可以扩展和重新定义现有对象的行为

“sealed”关键字的存在是否有充分的理由

例如,, 中的NotifyCollectionChangedEventArgs Silverlight是密封的。我想 创建我自己的版本 支持 添加范围和删除范围,但 Silverlight版本的NCCEA没有 提供一个支持 新项目和新项目的多个项目 OldItems属性,已定义为ILists。通常,我只是 用我自己的变体扩展类 覆盖了新项目和 OldItems属性,但在本例中 我不能也看不出有什么原因 应该是这样


简单的回答是,因为微软是这么说的。较长的答案是,微软提供了一种扩展密封类的机制,称为扩展方法

一般来说,扩展没有源代码的类是个坏主意。例如,您不知道调用base方法对对象的内部数据做了什么。是的,你可以使用反射器或者其他任何东西来解决这个问题,但是一般来说,使用合成或者扩展方法要好得多


你也必须考虑什么是遗传。它不仅仅是改变类的一种方式,它还提供了多态性。如果更改字符串类的语义,然后将新的字符串类传递给期望字符串以特定方式运行的对象,该怎么办?sealed本质上是强制执行契约,即此对象将始终按照您期望的方式工作。

虽然我确实同意.NET可能密封太多,但它通常是为了保护生态系统的完整性。当您的首要任务之一是保持整个框架/API/运行时的稳定,并且类之间存在一些脆弱的相互依赖关系时,最安全的方法可能是防止人们重写该行为并无意中破坏核心功能


尽管如此,我还是倾向于认为.NET团队封印了太多的类。密封有时可能是开发人员的简单懒惰,因为正确的类设计会带来太多工作。

我今天问的一个相关问题的答案可能有助于澄清密封类的目的:

我发现自己也在问同样的问题 问题,直到我开始工作 我自己的可重用库。许多的 有时你会上某些课程 这是不可能扩展的 需要模糊或神秘的序列 来自实现者的调用数

当你允许你的班级 延伸,你必须问:如果 开发人员扩展我的类,并通过 我可以把这门新课带到我的图书馆吗 透明地使用这个新的 上课?我能正常使用这个吗 新班级?这门新课真的吗 你也要这样做吗

我发现大多数时候 Net框架中的密封类 有一定的秘密 您不知道的需求, 考虑到目前的情况 实施不可能安全 暴露于子类


现在,请遵循该链接并向上投票给实际作者。

不要深入挖掘,请理解,当存在潜在的安全性、可维护性或向后兼容性问题时,Microsoft倾向于密封一个类。例如,
System.String
是出于安全和性能原因而密封的

在这种情况下,您需要询问Microsoft开发人员为什么选择密封该类。然而,我最近阅读的建筑指导文献倾向于采用“除非你知道它需要扩展”的方法。这些文献倾向于在可能的情况下使用扩展方法。(我不是说我同意,我只是说这是我最近读到的。)

即使类没有被密封,所讨论的属性也可能不是虚拟的,这仍然会使您处于困境

在您的特定场景中,我将使用具有您自己唯一名称的扩展方法。这是你所能做的一切。

设计可扩展的类(或框架)并不简单,简单地说,继承并不是面向对象编程的唯一原则

因此,
sealed
的存在是为了允许开发人员/设计师表达并保留这些意图。通过减少维护负担,密封类也可以使他们的生活更轻松。它允许原始开发人员控制类(或框架)的扩展方式,这样他们就可以进行内部更改,而不用担心破坏对其他代码的更改

一个原则是,默认情况下,开发人员应该密封任何leaf类。然后,当开发人员有意创建未密封的类时,它会迫使他们考虑可扩展性



Ref:Eric Lippert-

视情况而定,有些类只打算实例化(继承,如果存在的话,仅用于简化实现),其他类则打算继承以提供特定的实现

密封类有一些优点:

  • 他们没有任何虚拟方法,所以他们不必担心非“异常安全”实现的重写方法
  • 如果一个类是不可变的,它可以保持并保证不可变性

否则,如果您想用“舒适”方法装饰一个密封的类,请使用扩展方法(C#3.0)。

仅仅因为某个对象是对象,并不意味着每个人都应该完全开放来扩展或重新定义它的行为

一个很好的类比是
    public virtual void Insert()
    {
        Console.WriteLine("Parent insert");
    }
  class DbChildClass : DbParent
  {
  public void  Insert()
    {
        Console.WriteLine("Child inserts");
    }
  class DbParent
  {
  public  void Add() // Adds method with out consulting
  {
  this.Insert();
  }

  public virtual void Insert()
  {
        Console.WriteLine("Parent insert");
  }
  }
  DbChildClass o = new DbChildClass();
  o.Add();
  Console.Read();