在C#中,析构函数和类中的Finalize方法有什么区别?

时间:2009-07-02 22:28:09

标签: c# destructor finalize

在类中析构函数和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'使用相同的参数类型

3 个答案:

答案 0 :(得分:63)

维基百科对destructor文章中的终结者与finalizer之间的区别进行了一些很好的讨论。

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

~ClassName() { }

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

According to Microsoft,终结器引用垃圾收集器在收集(Finalize)时调用的函数,而析构函数是你执行结果的代码(语法糖变为Finalize)。它们非常接近于微软应该从未做过区分的事情。

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

答案 1 :(得分:59)

C#中的析构函数覆盖System.Object.Finalize方法。您必须使用析构函数语法来执行此操作。手动覆盖Finalize会给您一条错误消息。

基本上,您尝试使用Finalize方法声明的方法是hiding基类的方法。它将导致编译器发出警告,该警告可以使用new修饰符进行静音(如果它将起作用)。这里需要注意的重要一点是,不能同时override并同时声明一个名称相同的new成员,因此同时拥有析构函数和{{{ 1}}方法会导致错误(但是可以,虽然不推荐,但如果您没有声明析构函数,则声明Finalize方法。)

答案 2 :(得分:18)

Found here: http://sanjaysainitech.blogspot.com/2007/06/difference-between-destructor-dispose.html

  
      
  1. 析构

         

    它们是包含对象清理代码的特殊方法。   您无法在调用代码时显式调用它们   GC隐含地。在C#中,它们的名称与前面的类名相同   通过~标志。象 -

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

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

  2.   
  3. 处置

         

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

  4.   
  5. 的Finalize

         

    Finalize方法可以作为清理资源的保障措施   不调用Dispose方法的事件。你应该只   实现Finalize方法来清理非托管资源。您   不应该为托管对象实现Finalize方法,因为   垃圾收集器自动清理托管资源。   Finalize方法由GC隐式调用,因此你不能   从你的代码中调用它。

         

    注意:在C#中,Finalize方法无法覆盖,所以你必须这样做   使用析构函数,其内部实现将覆盖   在MSIL中完成方法。但是在VB.NET中,Finalize方法可以   覆盖因为它确实支持析构函数方法。

  6.   

更新: Interesting semi-related thread here