c# - Dispose() 用于清理托管资源?

标签 c# dispose finalize

this answer我发现,

Cleanup the unmanaged resources in the Finalize method and the managed ones in the Dispose method, when the Dispose/Finalize pattern has been used in your code.

后来我找到了this nice article关于完成和处置并对它们有一个清晰的认识。文章有如下代码(第3页),解释概念:

class Test : IDisposable
{
    private bool isDisposed = false;

    ~Test()
    {
       Dispose(false);
    }

    protected void Dispose(bool disposing)
    {
       if (disposing)
       {
          // Code to dispose the managed resources of the class
       }
       // Code to dispose the un-managed resources of the class

       isDisposed = true;
    }

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

但在其下方,会出现相同的注释(我将其包含在该问题的开头)。

The Dispose/Finalize Pattern Microsoft recommends that you implement both Dispose and Finalize when working with unmanaged resources. The correct sequence then would be for a developer to call Dispose. The Finalize implementation would run and the resources would still be released when the object is garbage collected even if a developer neglected to call the Dispose method explicitly. Francesco Balena writes in his blog "the Dispose/Finalize pattern should be used only when your type invokes unmanaged code that allocates unmanaged resources (including unmanaged memory) and returns a handle that you must use eventually to release the resource. Both dispose and finalize must chain up to their parent objects by calling their parent's respective methods after they have disposed or finalized their own members". Simply put, cleanup the unmanaged resources in the Finalize method and the managed ones in the Dispose method, when the Dispose/Finalize pattern has been used in your code.

现在我又糊涂了。在整篇文章和代码示例中,表明应在 Dispose() 中释放非托管资源。但是,该评论的相关性是什么?

编辑:

确认这一行:

Simply put, cleanup the unmanaged resources in the Finalize method and the managed ones in the Dispose method, when the Dispose/Finalize pattern has been used in your code

是错误的,我编辑了this answer .

最佳答案

看到它很简单。

  1. 如果您正在处理非托管资源 - 实现DisposeFinalizeDispose 将由开发人员调用,以便在他们发现不再需要资源时立即释放资源。如果他们忘记调用 Dispose,那么 Framework 会在它自己的 GC 周期中调用 finalize(通常会花费它自己的甜蜜时间)。
  2. 如果您的对象在内部使用一次性对象 - 如果您创建并保留对实现 Dispose( ) 以及您尚未处置的内容。
  3. 如果以上都不是这种情况(您不是在处理非托管资源,也不是您的对象在内部使用一次性对象)- 那么不要做任何事情。不要实现 FinalizeDispose

一些经典的例子:

System.IO.FileStream 对象管理文件的锁/流句柄。所以它实现了 dispose 和 finalize。如果开发人员处置它,那么其他程序可以立即访问它。如果他忘记处理它,那么框架会最终确定它并在其 GC 周期的后期关闭句柄。

System.Text.StringBuilder 没有任何非托管资源。所以没有处置没有定型。

就模式而言,它意味着什么

// Code to dispose the managed resources of the class

是调用您在该类中作为组件拥有的任何 .NET 对象的 Dispose 方法

// Code to dispose the un-managed resources of the class

表示关闭原始句柄和指针。这是带有示例的更新代码

class Test : IDisposable
{
  private bool isDisposed = false;

  ~Test()
  {
    Dispose(false);
  }

  protected void Dispose(bool disposing)
  {
    if (!isDisposed)
    {
      if (disposing)
      {
        // Code to dispose the managed resources of the class
        internalComponent1.Dispose();
        internalComponent2.Dispose();
      }

      // Code to dispose the un-managed resources of the class
      CloseHandle(handle);
      handle = IntPtr.Zero;   

      isDisposed = true;
    }
  }

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

Here is an old question解释一下

关于c# - Dispose() 用于清理托管资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16601929/

相关文章:

c# - 一个类中的测试是否保证不会同时执行?

c# - 通过C#应用程序访问西门子S7-1200

entity-framework - 延迟加载异常( Entity Framework )

java - Android:在实体调用 Finalize 时插入数据库

c# - 初学者数据库最佳实践

c# - 确定从转储文件中抛出异常的线程

flutter - 如何完全处理我的 Stateful Widget?

java - Java GUI 中的退出冲突

java与免费c函数的绑定(bind): how to correctly free an object

java - Java 中 Finalize() 操作的顺序