C# 析构函数和终结器之间的区别是什么?
请注意:这个问题是关于“析构函数”和“终结器”这两个词的术语差异及其正确用法。我仅提供了在C#和C++/CLI中使用它们的示例,以说明我提出这个问题的原因。我很清楚它是如何在C#和CLR中实现的,但我想知道术语的正确用法。C# 析构函数和终结器之间的区别是什么?,c#,terminology,destructor,finalizer,C#,Terminology,Destructor,Finalizer,请注意:这个问题是关于“析构函数”和“终结器”这两个词的术语差异及其正确用法。我仅提供了在C#和C++/CLI中使用它们的示例,以说明我提出这个问题的原因。我很清楚它是如何在C#和CLR中实现的,但我想知道术语的正确用法。 在C#世界中,“析构函数”和“终结器”这两个术语似乎可以互换使用,我怀疑这是因为C#规范使用“析构函数”一词来描述非确定性清理功能,而CLR文档总是使用“终结器”一词,所以在C#的范围内,它们的意思是一样的 但是,在C++/CLI规范中,这两者之间有区别。它允许确定性和非确
在C#世界中,“析构函数”和“终结器”这两个术语似乎可以互换使用,我怀疑这是因为C#规范使用“析构函数”一词来描述非确定性清理功能,而CLR文档总是使用“终结器”一词,所以在C#的范围内,它们的意思是一样的 但是,在C++/CLI规范中,这两者之间有区别。它允许确定性和非确定性清理,并使用术语“析构函数”表示确定性功能,使用术语“终结器”表示非确定性功能: 终结器提供非确定性清理。终结器是在垃圾收集过程中执行的“最后一次机会”函数,通常在未执行析构函数的对象上执行 此外,Wikipedia对和的描述表明析构函数和终结器是独立的概念,并支持C++/CLI规范使用与确定性相关的术语: 与析构函数不同,终结器不是确定性的。当程序显式释放对象时,将运行析构函数。相反,当内部垃圾收集系统释放对象时,将执行终结器 问题是:
- 从计算机科学的角度来看,“析构函数”和“终结器”之间是否有明确定义的区别,或者术语是否只能在上下文中定义
- 如果存在明确定义的差异,那么为什么C#规范会使用“错误”的术语
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日,语言设计委员会希望保留一种可能性,即“析构函数”可以作为终结器以外的东西实现。也就是说,“析构函数”被设计成