为什么Finalize和Dispose方法之间存在分离?

时间:2017-06-29 15:18:40

标签: c# garbage-collection resources dispose finalize

从MSDN文章中实现Finalize;

  

您应该为使用非托管资源的类重写Finalize,例如文件句柄或数据库连接,当在垃圾回收期间丢弃使用它们的托管对象时,必须释放这些资源。

从MSDN文章中实现IDisposible.Dispose;

  

使用此方法可以关闭或释放非托管资源,例如实现此接口的类实例所拥有的文件,流和句柄。按照惯例,此方法用于与释放对象持有的资源或准备对象以供重用相关的所有任务。

即使在每篇(全文)的文章中,似乎都是一个非常含糊不清的定义。

我真的失去了终结的目的,就在这里;

  

由于垃圾收集是非确定性的,因此您无法准确知道垃圾收集器何时执行完成。要立即释放资源,您还可以选择实现dispose模式和IDisposable接口。 您的类的使用者可以调用IDisposable.Dispose实现来释放非托管资源,并且可以在未调用Dispose方法的情况下使用Finalize方法释放非托管资源

我是否应该同时实施这两项工作,并在消费应用程序忘记处理我的对象的情况下强制自行完成?

与GC密切合作对我来说是新的......我想确保我正确地放弃我的资源。但是,我并不完全理解为什么这两个存在,或何时使用每一个。

2 个答案:

答案 0 :(得分:0)

使用Dispose模式实现两者。 Visual Studio甚至会为您安装脚手架。 Dispose允许您在完成后立即剥离稀缺资源。如果由于某种原因消费者忘记调用您的Dispose方法但允许其类实例超出范围,则Finalizer允许您处置它们。

答案 1 :(得分:-1)

如果你有非托管资源,只需实现IDisposable模式:

public class ApiClient : IDisposable 
{  
    private readonly HttpClient http = new HttpClient();

    public void Dispose()
    {  
        Dispose(true);  
        GC.SuppressFinalize(this);  
    }  

    protected virtual void Dispose(bool disposing)
    {  
        if (disposing)
        {
            http?.Dispose();  
        }  
    }  
}

详细了解一次性模式here。我永远不会忘记对我的一次性对象使用using语句来确保调用dispose方法:

using (var api = new ApiClient()) 
{
    // use api
}