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

Jef*_*ard 91 c# destructor finalize

在类中的析构函数和Finalize方法之间有什么区别?

我最近发现Visual Studio 2008认为析构函数与Finalize方法同义,这意味着Visual Studio不会让您同时在类中定义这两个方法.

例如,以下代码片段:

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

    public bool Finalize()
    {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Ken*_*nzi 69

Wikipedia 对终结器文章中终结器和析构函数之间的区别进行了一些很好的讨论.

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

~ClassName() { }
Run Code Online (Sandbox Code Playgroud)

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

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

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


Meh*_*ari 64

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

基本上你要对Finalize方法声明做的是隐藏基类的方法.它将导致编译器发出警告,该警告可以使用new修饰符进行静音(如果它将起作用).这里需要注意的重要一点是,你不能同时override声明一个new具有相同名称的成员,因此同时使用析构函数和Finalize方法都会导致错误(但是,尽管不推荐,但是你可以声明一个public new void Finalize()方法,如果你没有声明一个析构函数).


And*_*mer 19

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

  1. 析构函数

    它们是包含对象清理代码的特殊方法.您无法在代码中显式调用它们,因为GC会隐式调用它们.在C#中,它们的名称与~符号前面的类名相同.喜欢-

    Class MyClass
    {
    
    ~MyClass()
    {
    .....
    }
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

  2. 部署

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

  3. 最终确定

    如果未调用Dispose方法,Finalize方法可以作为清理资源的安全措施.您应该只实现Finalize方法来清理非托管资源.您不应该为托管对象实现Finalize方法,因为垃圾收集器会自动清理托管资源.Finalize方法由GC隐式调用,因此您无法从代码中调用它.

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

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