C# 析构函数和终结器之间的区别是什么?

C# 析构函数和终结器之间的区别是什么?,c#,terminology,destructor,finalizer,C#,Terminology,Destructor,Finalizer,请注意:这个问题是关于“析构函数”和“终结器”这两个词的术语差异及其正确用法。我仅提供了在C#和C++/CLI中使用它们的示例,以说明我提出这个问题的原因。我很清楚它是如何在C#和CLR中实现的,但我想知道术语的正确用法。 在C#世界中,“析构函数”和“终结器”这两个术语似乎可以互换使用,我怀疑这是因为C#规范使用“析构函数”一词来描述非确定性清理功能,而CLR文档总是使用“终结器”一词,所以在C#的范围内,它们的意思是一样的 但是,在C++/CLI规范中,这两者之间有区别。它允许确定性和非确

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


在C#世界中,“析构函数”和“终结器”这两个术语似乎可以互换使用,我怀疑这是因为C#规范使用“析构函数”一词来描述非确定性清理功能,而CLR文档总是使用“终结器”一词,所以在C#的范围内,它们的意思是一样的

但是,在C++/CLI规范中,这两者之间有区别。它允许确定性和非确定性清理,并使用术语“析构函数”表示确定性功能,使用术语“终结器”表示非确定性功能:

终结器提供非确定性清理。终结器是在垃圾收集过程中执行的“最后一次机会”函数,通常在未执行析构函数的对象上执行

此外,Wikipedia对和的描述表明析构函数和终结器是独立的概念,并支持C++/CLI规范使用与确定性相关的术语:

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

问题是:

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

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


我相信“析构函数”是C代码,“终结器”是编译的CIL方法。C#编译器将析构函数转换为终结器

编辑:更详细;C语言规范将“析构函数”定义为类上的C实例方法因此,析构函数是C#文法的一部分——析构函数是出现在源代码中的语言对象

析构函数是实现析构函数类实例所需操作的成员。析构函数不能有参数,不能有可访问性修饰符,也不能显式调用。实例的析构函数在垃圾收集期间自动调用

“finalizer”是公共语言运行库中使用的一个术语,例如在调用
GC.WaitForPendingFinalizers()
时,它指的是任何.net语言,而不仅仅是C。任何.net引用类型都可以有终结器。对于C#类(源代码工件),析构函数编译成CIL方法,该方法是CLR类型的终结器

或者更简洁地说,析构函数是终结器,就像源代码是机器代码一样;)

如果我们遵守析构函数的“确定性”定义,那么我会说在.NET对象中没有析构函数,除非通过使用显式实现。

严格地说,C#没有析构函数(我认为C#规范在这一点上令人困惑)。 C的终结器看起来像C++析构函数,但是,正如你所说,是不确定性的。 C#以
IDisposable::Dispose
的形式进行确定性清理(但这仍然不是析构函数)

C++ +CLI具有确定性析构函数,它看起来像C++析构函数。在CLI级别,这些映射到

IDisposable::Dispose()
IDisposable
是为您实现的)。 C++/CLI具有非确定性终结器,看起来像析构函数,但使用!前缀而不是^prefix

<> P>> C +/CLI使用C++为终结器使用的析构函数相同的语法,这可能有点令人困惑,但它更适合C++,它具有确定性破坏的强大传统。

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

[更新] 自从我最初在这里发布帖子以来,埃里克·利珀特(Eric Lippert)已经发布了他的回复(被接受的答案),并在同一个网站上发布了一篇文章。我很高兴看到我们达成了一致:-)工业界或学术界使用的“析构函数”和“终结器”之间有明确的区别吗

显然有。不同之处似乎在于析构函数是确定性调用的清理方法,而终结器在垃圾收集器通知它们时运行

2) 在这种情况下,C#规范就错了——终结器在C#中称为“析构函数”。为什么C#spec的作者们弄错了

我不知道,但我能猜到。事实上,我有两个猜测

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

见鬼,据我所知,这两个术语在1999年5月12日是相同的,而定义上的差异只是在后来才发展起来的,因为很明显,需要消除急切清理方法和懒惰清理方法之间的歧义

猜测#2是在1999年5月12日,语言设计委员会希望保留一种可能性,即“析构函数”可以作为终结器以外的东西实现。也就是说,“析构函数”被设计成