【问题标题】:All types have Finalize method inherited from Object?所有类型都有从 Object 继承的 Finalize 方法?
【发布时间】:2021-04-09 08:09:22
【问题描述】:

我们知道,当一个类型覆盖 Finalize 方法时,它必须在垃圾收集中幸存下来,它会被提升到另一代,这迫使对象的寿命比它应该的长得多。这在内存消耗方面并不理想,因此您应该尽可能避免完成。

但是不是所有类型都隐式派生自ObjectObject 确实有一个默认的 Finalize 方法,所以 CLR 应该考虑所有类型都有 Finalize 方法,因此堆上的所有对象都会被提示到新生代,并且比他们应该活得更长?

【问题讨论】:

  • 来自the docs:“Object 类没有提供 Finalize 方法的实现,并且垃圾收集器不会标记从 Object 派生的类型以进行终结,除非它们覆盖 Finalize 方法。”

标签: c# .net


【解决方案1】:

正如@canton7 在评论中所说,运行时足够聪明,可以知道如果实例的继承链中除了Object.Finalize 之外没有终结器,那么它不必将实例标记为终结器。 the documentation的相关部分是:

Object 类不提供Finalize 方法的实现,并且垃圾收集器不会将派生自Object 的类型标记为终结,除非它们覆盖Finalize 方法。

有趣的是,the C# specificationthe ECMA CLI specification 都没有强制执行此行为。允许一致的运行时实现始终调度所有对象以进行最终确定。但是,正如您在问题中所认识到的那样,这会导致垃圾收集的巨大开销,因此不切实际。


注意:C# 规范的相关部分是 §8.9 和 §15.2 以及 ECMA CLI 规范的 I.8.9.6.7。

【讨论】:

  • @canton7 我认为 C# 6.0 规范草案实际上是规范的最新版本,但在这种情况下,它们的区别仅在于命名终结器和析构函数。
  • 我链接到 MSDN 是因为 GitHub 文档有一个四处走动的习惯(特别是当您链接到一个分支名称时,而不是按 y 并获得更好的标识符)。特别是,我希望当 C# 6 规范退出草稿时,该文档会移动。我认为 MSDN 链接可能寿命更长
  • @canton7 TIL 在 GitHub 上按 y 会为您提供 SHA 链接。
猜你喜欢
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 1970-01-01
  • 2014-01-04
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多