110

类中的析构函数和 Finalize 方法之间有什么区别(如果有的话)?

我最近发现 Visual Studio 2008 将析构函数视为 Finalize 方法的同义词,这意味着 Visual Studio 不会让您在一个类中同时定义这两种方法。

例如,下面的代码片段:

class TestFinalize
{
    ~TestFinalize()
    {
        Finalize();
    }

    public bool Finalize()
    {
        return true;
    }
}

在析构函数中调用 Finalize 时出现以下错误:

以下方法或属性之间的调用不明确:“TestFinalize.~TestFinalize()”和“TestFinalize.Finalize()”

如果对 Finalize 的调用被注释掉,则会出现以下错误:

类型“ManagementConcepts.Service.TestFinalize”已经定义了一个名为“Finalize”的成员,具有相同的参数类型

4

3 回答 3

75

维基百科在终结器文章中对终结器和析构器之间的区别进行了很好的讨论。

C# 真的没有“真正的”析构函数。语法类似于 C++ 析构函数,但它确实是终结器。您在示例的第一部分中正确编写了它:

~ClassName() { }

以上是Finalize函数的语法糖。它确保基础中的终结器保证运行,但在其他方面与覆盖Finalize函数相同。这意味着当您编写析构函数语法时,您实际上是在编写终结器。

根据 Microsoft的说法,终结器是指垃圾收集器在收集 ( Finalize) 时调用的函数,而析构器是作为结果执行的代码位(成为 的语法糖Finalize)。它们是如此接近于相同的东西,以至于微软不应该做出区分。

Microsoft 对 C++ 的“析构函数”术语的使用具有误导性,因为在 C++ 中,只要对象被删除或从堆栈中弹出,它就会在同一个线程上执行,而在 C# 中,它会在另一个时间在单独的线程上执行。

于 2011-11-28T16:45:56.743 回答
73

C# 中的析构函数会覆盖System.Object.Finalize方法。你必须使用析构函数来做到这一点。手动覆盖Finalize会给您一条错误消息。

基本上你试图用你的Finalize方法声明做的是隐藏基类的方法。它将导致编译器发出警告,可以使用new修饰符将其静音(如果它可以工作)。这里要注意的重要一点是,您不能同时override声明new具有相同名称的成员,因此同时拥有析构函数和Finalize方法将导致错误(但您可以,虽然不推荐,但public new void Finalize()如果你没有声明一个析构函数)。

于 2009-07-02T22:30:48.323 回答
21

在这里找到:http://sanjaysainitech.blogspot.com/2007/06/difference-between-destructor-dispose.html

  1. 析构函数

    它们是包含对象清理代码的特殊方法。您不能在代码中显式调用它们,因为它们被 GC 隐式调用。~在 C# 中,它们与前面带有符号的类名具有相同的名称。像-

    Class MyClass
    {
    
    ~MyClass()
    {
    .....
    }
    }
    

    在 VB.NET 中,析构函数是通过重写 System.Object 类的 Finalize 方法来实现的。

  2. 处置

    这些就像类中的任何其他方法一样,可以显式调用,但它们具有清理对象的特殊目的。在 dispose 方法中,我们为对象编写清理代码。重要的是,我们释放了 dispose 方法中的所有非托管资源,如数据库连接、文件等。实现 dispose 方法的类应该实现 IDisposable 接口。Dispose 方法应该为它正在处理的对象调用 GC.SuppressFinalize 方法,如果类有析构函数,因为它已经完成了清理对象的工作,那么垃圾收集器就没有必要调用对象的 Finalize 方法了。参考: http: //msdn2.microsoft.com/en-us/library/aa720161 (VS.71).aspx

  3. 敲定

    在未调用 Dispose 方法的情况下,Finalize 方法可作为清理资源的保护措施。您应该只实现一个 Finalize 方法来清理非托管资源。您不应为托管对象实现 Finalize 方法,因为垃圾收集器会自动清理托管资源。Finalize 方法由 GC 隐式调用,因此您不能从代码中调用它。

    注意:在 C# 中,Finalize 方法不能被覆盖,所以必须使用析构函数,其内部实现会覆盖 MSIL 中的 Finalize 方法。但是在 VB.NET 中,Finalize 方法可以被覆盖,因为它确实支持析构函数方法。

更新: 这里有趣的半相关线程

于 2009-07-02T22:30:24.297 回答