为什么“密封”会发生? .Net 中存在关键字吗?

发布于 2024-07-13 16:23:34 字数 512 浏览 10 评论 0原文

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

“sealed”关键字的存在有充分的理由吗?

举个例子, NotifyCollectionChangedEventArgs 中 Silverlight 已被密封。 我想要 创建我自己的版本 支持的 ObservableCollection AddRange 和RemoveRange,但是 Silverlight 版本的 NCCEA 没有 提供一个支持的构造函数 NewItems 的多个项目和 OldItems 属性,已定义为 IList。 通常,我只是 用我自己的变体扩展类 覆盖了 NewItems 和 OldItems 属性,但在本例中 我不能,我也看不出为什么 情况应该如此。

A large number of classes in the .Net framework are marked as 'sealed', preventing you from inheriting those classes with your own. Surely this goes against the nature of object orientation, where you can extend and redefine the behaviour of existing objects.

Is there a good reason for the existence of the 'sealed' keyword?

As an example,
NotifyCollectionChangedEventArgs in
Silverlight is sealed. I wanted to
create my own version of
ObservableCollection that supported
AddRange and RemoveRange, but the
Silverlight version of NCCEA doesn't
provide a constructor that supports
multiple items for the NewItems and
OldItems properties, which are already defined as ILists. Usually, I'd just
extend the class with my own variant
that overrode the NewItems and
OldItems properties, but in this case
I can't and I can see no reason why
that should be the case.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

傾城如夢未必闌珊 2024-07-20 16:23:34

将类(或框架)设计为可扩展并非易事,简单来说继承并不是面向对象编程的唯一原则。

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

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


参考:Eric Lippert - 为什么这么多框架类被密封?

Designing classes (or frameworks) to be extensible isn't trivial, and put simply inheritance is not the single principle of Object Oriented programming.

So sealed exists to allow the developer / designer to express and preserve those intentions. Sealing a class can also make their life easier by reducing the maintenance burden. It allows the original developer to control how the class (or framework) is extended, so they can make internal changes without worrying about breaking changes to others code.

One principle is that developers should seal any leaf classes by default. Then, when the developer creates an unsealed class intentionally, it forces them to think about extensibility.


Ref: Eric Lippert - Why Are So Many Of The Framework Classes Sealed?

聆听风音 2024-07-20 16:23:34

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

我发现自己也在问同样的问题
问题直到我开始工作
我自己的可重用库。 许多
有时你最终会选择某些课程
如果没有的话就无法扩展
需要晦涩或神秘的序列
来自实施者的调用。

当允许你的班级
扩展,你必须问:如果
开发人员扩展了我的课程,并通过了
这个新课程到我的图书馆,我可以吗
透明地使用这个新的
班级? 我可以正常使用这个吗
新班级? 这真的是新班级吗
会表现得一样吗?

我发现大多数时候
.Net Framework 中的密封类
有一定的幕后
你不知道的要求,
考虑到当前的
实施不能安全
暴露给子类。

里氏替换和组合

现在点击该链接并为实际作者投票。

This answer from a somewhat related question I asked today might help clarify the purposes of sealing a class:

I found myself asking that same
question until I started working on
reusable libraries of my own. Many
times you wind up with certain classes
that just cannot be extended without
requiring obscure or arcane sequences
of calls from the implementor.

When allowing your class to be
extended, you have to ask: if a
developer extends my class, and passes
this new class to my library, can I
transparently work with this new
class? Can I work properly with this
new class? Is this new class really
going to behave the same?

I've found that most of the time the
sealed classes in the .Net Framework
have certain under-the-hood
requirements that you aren't aware of,
and that given the current
implementation cannot be safely
exposed to subclasses.

Liskov Substition and Composition

Now follow that link and upvote the actual author.

奢欲 2024-07-20 16:23:34

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

一般来说,扩展没有源代码的类是一个坏主意。 例如,您不知道调用基本方法对对象的内部数据做了什么。 是的,您可以使用反射器或其他任何东西来解决它,但一般来说,使用组合或扩展方法会更好。

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

The short answer is, because Microsoft said so. The longer answer is that Microsoft has provided a mechanism to extend sealed classes, called extension methods.

In general, it's a bad idea to extend classes which which you don't have source code to. For example, you don't know what calling base method does to the internal data of the object. Yes, you can use reflector or whatever to figure it out, but in general it's much better to use composition or extension methods.

You also have to consider what inheritence actually is. It's not just a way to alter the class, it also provides polymorphism. What if you change the semantics of, say, the string class, then you pass your new string class to an object that expects a string to act in a specific way? sealed essentially enforces the contract that this object will always work the way you expect it to.

心头的小情儿 2024-07-20 16:23:34

无需深入挖掘,即可了解当存在必须在下游处理的潜在安全性、可维护性或向后兼容性问题时,Microsoft 倾向于密封一个类。 例如,出于安全和性能原因,System.String 被密封。

在这种特殊情况下,您需要询问 Microsoft 开发人员为什么他们选择密封该类。 然而,我最近阅读的架构指导文献倾向于采用“密封的方法,除非您知道它需要扩展”。 这些文献倾向于支持在可能的情况下使用扩展方法。 (我并不是说我同意它;我只是说这就是我最近读过的内容。)

即使该类没有被密封,所讨论的属性也可能不是虚拟的,这仍然会留下你在这儿的小溪上。

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

Without digging too deeply, understand that Microsoft favors sealing a class when there are potential security, maintainability or backwards-compatibility issues that it will have to deal with downstream. For example, System.String is sealed for security and performance reasons.

In this particular case, you'd need to ask a Microsoft developer why they chose to seal that class. However, the architectural guidance literature I've been reading lately tends to favor an approach of "seal unless you know it will need to be extended." This literature tends to espouse using extension methods where possible. (I'm not saying I agree with it; I'm just saying that's what I've been reading lately.)

Even if the class weren't sealed, the properties in question might have been left not virtual, which would still leave you up the creek here.

In your specific scenario, I'd go with extension methods with your own unique names. It's about all you can do.

我一向站在原地 2024-07-20 16:23:34

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

不过,我确实倾向于认为 .NET 团队密封了太多的类。 密封有时可能是开发人员的简单懒惰,因为正确的类设计会需要太多工作。

While I do agree that .NET probably seals too much, it's generally to protect the integrity of an ecosystem. When one of your top priorities is to keep your overall framework/API/runtime stable, and there are somewhat fragile interdependencies between classes, it may be safest to prevent people from overriding that behavior and inadvertently destabilizing core functionality.

Though again, I do tend to feel that the .NET team seals too many classes. Sealing can sometimes be simple laziness on the part of the developer because a proper class design would be too much work.

寻找我们的幸福 2024-07-20 16:23:34

我认为除了保护无知的人之外,没有什么充分的理由来密封班级——呃,我的意思是无辜的。 你知道那句老话:“给他们足够的绳子,他们就会上吊自杀”。 我说让他们摇摆吧。 也许这就是我的 C++ 背景,但我很高兴知道,如果我不勤奋,我有能力完全把事情搞砸。

我倾向于通过接口编程。 这些接口当然是公共的,任何人都可以自由地提供自己的实现,该实现遵守接口所表达的契约。 我实现这些接口的具体类往往是私有问题,并被标记为内部和/或私有。 我觉得我没有必要封闭这样的课程。

当需要重用代码时,我会通过继承来避免重用,而倾向于组合和其他技术。

密封对于被认为是普通旧数据类型的类型也可能有效,但我不相信这一点会消失。

I would suggest that there is no good reason for sealing classes other than to protect the ignorant -err, I mean innocent. You know the old saying, "given them enough rope and they will hang themselves". Let them sway I say. Perhaps this is my C++ background, but I am quite comfortable knowing that I have the power to completely stuff things up if I am not diligent.

I tend to program by interface. The interfaces are of course public and any one is free to provide their own implementation that adheres to the contract expressed by the interface. My concrete classes that implement these interfaces tend to be a private concern and are marked internal and/or private. I don't feel that I need to seal such classes.

Where code reuse is desirable, I avoid reuse through inheritance, favouring composition and other techniques.

Sealing may also be valid on types that are considered plain-old-data types, but I'm not convinced wither way on this.

Bonjour°[大白 2024-07-20 16:23:34

这取决于,有些类旨在被实例化(继承,如果存在,则仅用于简化实现),其他类旨在被继承以提供特定的实现。

密封类有一些优点:

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

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

It depends, there are classes that are intended to be just instantiated (inheritance, if exists, is used just to simplify the implementation), other classes are intended to be inherited to provide a spesific implementation.

Sealed classes have some advantages:

  • they don't have any virtual methods, so they don't have to worry about non-"exception- safe" implemented overriding methods.
  • If a class is immutable it can preserve and guarantee the immutability.

Otherwise if you want to decorate a sealed class with "comfort" methods use the extension methods (C# 3.0).

错々过的事 2024-07-20 16:23:34

仅仅因为某个东西是一个对象,并不意味着它总是应该向每个人开放以扩展或重新定义它的行为。

一个很好的比喻是一扇门和一把锁。 门的本质是让人们通过它,这就是它的设计目的。 然而,大多数门都设计有锁,会限制人们通过它们的能力。 门是否有锁以及该锁是否默认上锁的决定由房间的建筑师根据房间里的东西以及谁应该有权访问它来决定,而不是根据它是一扇门这一事实。

当然,如果特定建筑物中的大多数门默认都是锁着的,尤其是当您确实想穿过一扇门时,这可能会令人沮丧。 :-) 我自己也去过那里,也问过同样的问题。 简而言之,有时在设计复杂的框架时,人们往往会在更加谨慎的方面犯一点错误,并默认密封类,除非有明确的场景需要扩展它们。

Just because something is an object, it doesn't mean it always should be wide open for everybody to extend or redefine it's behavior.

A good analogy would be a door and a lock. A door's nature is to let people to pass through it, that's what it's built for. Yet, most doors are designed with locks that can limit the ability of people to pass through them. The decision whether a door has a lock and whether that lock is locked by default is left to the architect of the room, based on what's in the room and who should have access to it, not on the fact that it's a door.

Of course, it can be frustrating if most of the doors in particular building are locked by default, especially if there's one you really want to go through. :-) I've been there myself and I've asked the same question. The short answer is that sometimes when designing a complex framework, people tend to err a little bit on the more cautios side and have classes sealed by default, unless there is explicit scenario that requires them to be extended.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文