析构函数和终结符之间的区别?

Gre*_*ech 36 c# destructor terminology finalizer

请注意:这个问题是关于"析构函数"和"终结器"之间的术语差异及其正确用法.我只提供了在C#和C++/CLI中使用它们的示例,以说明我提出问题的原因.我很清楚它是如何在C#和CLR中实现的,但我问的是术语的正确使用.


在C#世界中,术语"析构函数"和"终结器"似乎几乎可以互换使用,我怀疑是因为C#规范使用"析构函数"一词来描述非确定性清理功能,而CLR文档总是使用单词"终结者",所以在C#领域内他们的意思相同.

但是,在C++/CLI规范中,两者之间存在差异.它允许确定性和非确定性清理,并使用术语"析构函数"作为确定性功能,使用"终结器"作为非确定性功能:

终结器提供非确定性清理.终结器是在垃圾收集期间执行的"最后机会"函数,通常在未执行析构函数的对象上执行.

另外,维基百科对析构函数终结器的描述表明析构函数终结符是单独的概念,并且支持C++/CLI规范使用与确定性有关的术语:

与析构函数不同,终结器不是确定性的.当程序显式释放对象时,将运行析构函数.相反,当内部垃圾收集系统释放对象时,执行终结器.

问题:

  • 从计算机科学的角度来看,是否存在"析构函数"和"终结器"之间明确定义的区别,或者术语是否只能在上下文中定义?

  • 如果存在明确定义的差异,那么为什么C#规范会使用"错误"的术语?

Eri*_*ert 39

1)工业界或学术界使用的"析构者"和"终结者"之间是否有明确的区别?

肯定有.差异似乎是析构函数是确定性调用的清理方法,而终结器在垃圾收集器告诉它们时运行.

2)在这种情况下,C#规范错了 - 终结器在C#中称为"析构函数".为什么C#规范的作者弄错了?

我不知道,但我猜.事实上,我有两个猜测.

猜测#1是1999年5月12日没有维基百科的文章清楚地描述这两个概念之间的细微差别.那是因为没有维基百科.还记得没有维基百科吗?黑暗时代,男人.错误可能只是一个诚实的错误,相信这两个术语是相同的.

哎呀,就我所知,这两个词相同于1999年5月12日,并在定义的区别只是后来演变,因为很明显,有必要急切和懒惰的清除方法之间的歧义.

猜测#2是1999年5月12日,语言设计委员会希望保留"析构函数"可以被实现为终结者以外的其他东西的可能性.也就是说,"析构函数"被设计为C#语言概念,它不一定与.NET"终结器"概念一对一地映射.当设计一种语言与它所在的框架同时进行设计时,有时候你想要让自己与子系统中最新的设计变更隔离开来.

语言委员会1999年5月12日的笔记部分内容如下:

我们将对回收实例时执行的成员使用术语"析构函数".类可以有析构函数; 结构不能.与C++不同,析构函数不能显式调用.销毁是非确定性的 - 您无法可靠地知道析构函数何时执行,除非说它在对象的所有引用都已释放后的某个时刻执行.继承链中的析构函数按顺序调用,从大多数后代到最小后代.派生类不需要(也没有办法)显式调用基础析构函数.C#编译器将析构函数编译为适当的CLR表示.对于此版本,这可能意味着在元数据中区分的实例终结器.CLR可能会在未来提供静态终结器; 我们没有看到使用静态终结器对C#的任何障碍.

所以,在那里,你现在知道我在这个问题上所知道的一切.如果您想了解更多信息,请在下次见到他时询问Anders.

  • 有趣; 从笔记中可以看出,当时析构函数并不意味着决定论,所以我认为你可能是正确的,因为这是一种从那以后发展起来的区别. (2认同)

phi*_*red 6

严格来说C#没有​​析构函数(我相信C#规范在这一点上令人困惑).C#的终结器看起来像C++析构函数,但正如你所说,它是非确定性的.C#具有确定性的清理形式IDisposable::Dispose(但这仍然不称为析构函数).

C++/CLI具有确定性析构函数,看起来像C++析构函数.在CLI级别,这些映射到IDisposable::Dispose()(IDisposable为您实现).C++/CLI具有非确定性终结器,看起来像析构函数但使用!前缀而不是^前缀.

C++/CLI使用与C#用于终结器的析构函数相同的语法这一事实可能有点令人困惑 - 但它更适合C++,后者具有确定性破坏的强大传统.

不幸的是,缺乏这些术语的通用定义意味着你总是需要澄清你在说什么.我个人总是在谈论C#概念时使用终结器这个词,并为上下文保留析构函数,它肯定意味着确定性破坏.

[更新]自从我的原帖在这里Eric Lippert发布​​了他的回复(接受的回答)并随后发布一篇博文.我很高兴看到我们达成一致:-)

  • '问题'是C#确实称它为析构函数. (2认同)