1

据我了解,关于这个问题有两个阵营——第一个认为终结器是 C# 特有的析构函数。所以他们认为这两件事是一样的。

第二个阵营认为存在细微差别——在维基百科中写道——““析构函数”一词通常用于表示确定性调用的清理,而“终结器”则在垃圾收集器要求运行时运行。”

但让我为自己澄清一些事情。确定性调用的清理?在 C# 规范和 msdn 中写到不能调用析构函数(它们是自动调用的)。唯一可以自动调用它们的情况是垃圾收集器。

所以我看不出确定性调用的清理和垃圾收集器的情况有什么区别。

是这样还是不是?

4

6 回答 6

5

这是个很大的差异。确定性调用意味着您知道何时调用它。

在 C++ 中:

{
    Person a;
    a.Name = "John";
    InvitePerson(a);
} // <-- Destructor is always invoked when the scope is left

在 C# 中:

{
    Person a = new Person();
    a.Name = "John";
    InvitePerson(a);
} // <-- The finalizer is NOT invoked when the scope is left

正如所指出的,主要区别在于:
在 C# 和其他垃圾收集语言中,您不知道何时甚至是否会执行终结器。
但是,在 C++ 中,您确实知道析构函数何时以及在对象超出范围后立即执行。

于 2011-05-04T11:42:17.100 回答
3

官方立场是 C# 有析构函数 ( ~ClassName() {}),它们映射到System.Object.Finalize(). 在 VB.NET 中,您只需像 ToString 一样覆盖 Finalize。

虽然有些混乱,但你是对的。但更多的是关于 Finalize/Destructor 与 Dispose。这是Eric Lippert 的帖子(参考维基百科):

是的,根据这些定义,C# 规范弄错了。我们在规范中所说的“析构函数”实际上是一个终结器,而我们所说的由“using”语句调用的“Dispose()”方法实际上是一个“析构函数”。

于 2011-05-04T11:42:46.280 回答
1

在 C# 中,终结器和析构器是同一事物的不同名称。

C# 语言规范 (1.6.7.6) 实际上将这些称为析构函数。但是,由于名称析构函数很容易被误认为是 C++ 对应项(这与 C# 中的析构函数完全不同),因此使用术语终结器是有意义的。

于 2011-05-04T11:40:17.457 回答
1

第二种意见更正确。您无法确保对象的析构函数将在指定时间运行。所以它不是一个析构函数,就像在 C++ 中那样,你可以显式调用delete obj.

在 .NET 中,对于需要在使用后清理一些资源的对象,您应该实现 IDisposable 并在完成对象或using()块时显式调用 Dispose。

于 2011-05-04T11:41:54.900 回答
0

确定性意味着您可以在任何给定时间释放内存。这在 C# 中是不可能的,因为析构函数是由 GC 通过终结器线程在不确定的时间点调用的。

于 2011-05-04T11:42:36.537 回答
0

我认为这只是术语不同的情况。单词在不同文本中的定义/使用方式不同 - 一直在发生。

但是,如果您依赖垃圾收集器,则没有“确定性调用的清理”。你的结论:

所以我看不出确定性调用的清理和垃圾收集器的情况有什么区别。

...在您给出的上下文中没有意义。不同之处在于一个被确定性地调用,而另一个不是。

于 2011-05-04T11:42:50.860 回答