据我所知,有两个阵营涉及这个问题 - 第一个认为终结者是特定于C#的析构函数。所以他们认为这两件事是一样的。
第二阵营认为存在细微差别 - 用维基百科写的 - “术语”析构函数“通常用于表示确定性调用的清理,而”终结器“在垃圾收集器运行时运行。”
但是让我为自己澄清一些事情。确定性地调用清理?在C#规范和msdn中写道,无法调用析构函数(它们是自动调用的)。可以自动调用它们的唯一情况是垃圾收集器。
所以我没有看到确定性调用的清理与垃圾收集器的情况有任何区别。
是这样吗?
答案 0 :(得分: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 ++中,一旦对象超出范围,就会知道何时和 执行析构函数。
答案 1 :(得分:3)
官方立场是C#具有析构函数(~ClassName() {}
)并且它们映射到System.Object.Finalize()
。在VB.NET中,你只需像ToString一样覆盖Finalize。
是的,通过这些定义,C#规范 弄错了。我们称之为 规范中的“析构函数”实际上是一个 终结者,我们称之为 由a调用的“Dispose()”方法 “使用”声明实际上是一个 “析构函数”。
答案 2 :(得分:1)
在C#中,finalizer和析构函数是同一个东西的不同名称。
C#语言规范(1.6.7.6)实际上将这些称为Destructors。但是,由于名称析构函数可能很容易被误认为是C ++对应物(这与C#中的析构函数完全不同),因此使用术语终结器是有意义的。
答案 3 :(得分:1)
第二种观点更为正确。您无法确保对象的析构函数将在指定时间运行。所以它不是像C ++那样的descructor,你可以在其中显式调用delete obj
。
在.Net中,对于需要在使用后清理一些资源的对象,您应该实现IDisposable并在完成对象时显式调用Dispose,或者使用using()
块
答案 4 :(得分:0)
确定性意味着您可以在任何给定时间释放内存。这在C#中是不可能的,因为GC会在无限期的时间点通过终结器线程调用析构函数。
答案 5 :(得分:0)
我认为这只是一个不同术语的案例。在不同的文本中不同地定义/使用单词 - 一直发生。
但是,如果您依赖垃圾收集器,则没有“确定性调用的清理”。你的结论是:
所以我没有看到确定性调用的清理与垃圾收集器的情况有任何区别。
...在您提供的上下文中没有意义。区别在于一个是确定性调用的,另一个不是。