【问题标题】:Difference between destructor, dispose and finalize method析构函数、dispose 和 finalize 方法的区别
【发布时间】:2012-12-08 22:15:11
【问题描述】:

我正在研究垃圾收集器在 c# 中的工作原理。我对DestructorDisposeFinalize 方法的使用感到困惑。

根据我的研究和理解,在我的类中有一个 Destructor 方法将告诉垃圾收集器以析构方法中提到的方式执行垃圾收集,而该方法不能在类的实例上显式调用。

Dispose 方法旨在让用户控制垃圾回收。 Finalize 方法释放类使用的资源,但不释放对象本身。

我不确定我是否理解正确。请澄清疑惑。欢迎任何进一步的链接或指南。

【问题讨论】:

    标签: c# .net destructor dispose finalize


    【解决方案1】:

    析构函数隐式调用 Finalize 方法,它们在技术上是相同的。 Dispose 可用于实现 IDisposable 接口的对象。

    您可能会看到:Destructors C# - MSDN

    析构函数隐式调用了基类的 Finalize 对象。

    来自同一链接的示例:

    class Car
    {
        ~Car()  // destructor
        {
            // cleanup statements...
        }
    }
    

    析构函数的代码被隐式翻译成如下代码:

    protected override void Finalize()
    {
        try
        {
            // Cleanup statements...
        }
        finally
        {
            base.Finalize();
        }
    }
    

    你对析构函数的理解是对的:

    来自MSDN

    程序员无法控制何时调用析构函数 因为这是由垃圾收集器决定的。垃圾 收集器检查不再被 应用。如果它认为一个对象有资格销毁,它 调用析构函数(如果有)并回收用于存储的内存 物体。程序退出时也会调用析构函数。它是 可以通过调用 Collect 来强制进行垃圾收集,但大多数 时间,这应该避免,因为它可能会创建性能 问题。

    【讨论】:

    • 如何通过调用Collect() 强制垃圾回收可能会产生性能问题?
    • @Destructor,GC 的标记阶段使用 DFS,它相对于应用程序中的对象总数具有线性时间和空间复杂性。所以,最好还是让 GC 来决定什么时候使用这么多资源,不要自己去利用。
    【解决方案2】:

    在 C# 术语中,析构函数和终结器基本上是可互换的概念,应该用于在收集类型时释放 非托管 资源,例如外部句柄。您需要编写终结器非常很少见。

    问题在于 GC 是非确定性的,因此Dispose() 方法(通过IDisposable)可以支持确定性 清理。这与垃圾回收无关,并允许调用者尽快释放任何资源。它也适用于托管资源(除了非托管),例如,如果你有一个封装(比如)数据库连接的类型,你可能想要处理也释放连接的类型。

    【讨论】:

    • 所以我觉得Destructor方法应该只包含在其销毁之前必须执行的代码,Finalize方法将主要从超类继承。
    • @VictorMukherjee 再次,它们(析构函数和终结器)是可以互换的。 Dispose() 将被称为 before 销毁,但它既不称为析构函数也不是终结器
    • 嗨,Marc,认为 GC 主要是确定性的,只是规则不为人所知,是否正确?我不是专家,一直在学习,我想知道您的评论是否只是在终结者与处置的背景下泛泛而谈?还是它非常不确定(尽管这可能是另一天的另一个问题)?
    • @AlexKeySmith 我不得不说后者,因为它受时间、CPU 活动和外部因素(如外部内存)控制
    • 谢谢 Marc,这很有用;啊,所以即使基本规则是确定性的,它也受到应用程序控制之外的许多因素的控制,它实际上是非确定性的。感谢您的洞察力!
    猜你喜欢
    • 2011-01-16
    • 2013-07-26
    • 1970-01-01
    • 2010-11-07
    • 2011-04-08
    • 2015-01-05
    相关资源
    最近更新 更多