为什么Finalize和Dispose方法之间要有职责分离?

46 浏览
0 Comments

为什么Finalize和Dispose方法之间要有职责分离?

这个问题已经有答案了在C#中使用Finalize/Dispose方法

从Finalize实现的MSDN文章中;

对于使用未托管资源(如文件句柄或数据库连接)的类,应该重写Finalize。并在垃圾回收期间丢弃使用它们的托管对象时将其释放。

从IDisposable.Dispose的MSDN文章中;

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

即使在每个(详尽的)文章的语境下,它们似乎都是非常含糊的定义。

然而,我真正不了解Finalize的目的之处在于此;

由于垃圾回收是非确定性的,您不知道垃圾回收器何时执行最后处理。为了立即释放资源,您还可以选择实现dispose模式和IDisposable接口。IDisposable.Dispose实现可供您的类的消费者调用以释放未托管资源,或者在不调用dispose方法的情况下使用Finalize方法来释放未托管资源。

我应该同时实现这两个,以便在消费应用程序忘记处理我的对象时强制执行一个finalize吗?

与垃圾回收器如此密切地打交道对我来说是新事物......我想确保我正确地丢弃我的资源。然而,我并不完全理解为什么这两者都存在,或者何时使用每个选项。

admin 更改状态以发布 2023年5月24日
0
0 Comments

如果您有未管理的资源,请像这样实现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();  
        }  
    }  
}

有关可释放模式的更多信息,请在这里阅读。我从不忘记为我的可释放对象使用using语句,以确保调用dispose方法:

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

0
0 Comments

使用Dispose模式实现两者。Visual Studio甚至会为您提供脚手架。Dispose允许您在完成使用稀缺资源后立即解除它们的所有权。Finalizer允许您在消费者忘记调用Dispose方法但类实例可以超出作用域的情况下释放它们。

0