为啥是 IDisposable 接口? [复制]

Posted

技术标签:

【中文标题】为啥是 IDisposable 接口? [复制]【英文标题】:Why IDisposable interface? [duplicate]为什么是 IDisposable 接口? [复制] 【发布时间】:2020-11-09 14:00:01 【问题描述】:

我看过很多文章说 IDisposable 的目的是关闭非托管对象,如数据库连接和第三方报告。但我的问题是,如果我可以在我的方法中处理非托管对象,我为什么要定义 Dispose 方法没有定义 Dispose() 方法?

举个例子,

class Report : IDisposable

    public void GenerateReport()
    
        Report rpt=new Report() //unmanaged object created
        rpt.Dispose(); // Disposing the unmanaged object
    

    private void Dispose()
    
        //not sure why this block is needed
    

我的理解正确吗?

【问题讨论】:

嗨,杰。您可能会在***.com/questions/538060/… 找到您的问题(以及许多其他问题!)的答案。此外,如果这个问题最终被标记为重复,请不要感到惊讶 - 它之前已经介绍过:-) 【参考方案1】:

垃圾收集器 (GC) 可在整个 .Net 框架中使用,运行良好,很容易被遗忘。但是,值得学习与他一起工作并利用他的可能性。为此,IDisposable 接口的正确实现是必要的,如果我们考虑适当释放托管和非托管资源,则其基本形式有时是不够的。

这是扩展版本,在这种情况下非常有用。 在某种程度上回答了你的问题:

public class DisposableExtended: IDisposable

   private bool isDisposed = false;

public void Dispose ()

   this.Dispose (true);
   GC.SupressFinalize (this);

protected void Dispose (bool disposing)

     if (! this.isDisposed)
     
            if (disposing)
            
             // here we release managed resources (standard classes)
            
           // here we release unmanaged resources (e.g. streams, etc..)

     



  this .isDisposed = true;


~ DisposableExtended ()

  this.Dispose (false);

【讨论】:

【参考方案2】:

实现 IDisposable 接口的类可以在 using 块中使用。此解决方案的一大优点是,在离开块后,将自动调用在该区域中创建的对象的 Dispose 方法。这样,我们只能使用实现 IDisposable 接口的类。

//example :
using(var dClean= new DisposableClean())

    //after leaving this using dClean will be automatically destroyed 

您创建的对象需要公开一些方法,而不是必须命名为 Dispose()。你也可以称它为 Clean()。 Dispose() 是常规名称。

【讨论】:

【参考方案3】:

是的,您可以定义自己的方式来释放资源,但许多现有代码都使用这种方式。如果您将代码分享给他人,请记住告诉他们以您的方式处理。

实现IDisposable 的一个“好处”是您可以通过使用诸如using 之类的语言结构间接调用Dispose

例如:

using(Stream s = File.OpenRead("HelloWorld.bin"))
            
                //Do stuffs
            

【讨论】:

【参考方案4】:

您是正确的,您的示例中不需要实现 IDisposable。示例是,如果您在编写的课程的生命周期内保留一个长寿命的对象。所以说你有这个:

public class Report : IDisposable

  private Stream _reportStream; // This variable lives a long time.

  public void WriteToStream(byte[] data)
  
    _reportStream.Write(data, 0, data.Length);
  

  public void Dispose()
  
    _reportStream?.Dispose();
  

这是一个相当简单的示例,但它表明_reportStream 在类的长度内存在,并且需要与类同时进行清理和垃圾收集。没有什么能阻止你创建一个名为 CleanupObject() 的公共方法来做同样的事情,但是人们不能使用 using 块让运行时自动调用 Dispose():

using (var myReport = new Report())

  // do a bunch of things with myReport;
 // Here the runtime will call myReport.Dispose() for you.

// myReport isn't accessible from here, as it was declared in the using block

【讨论】:

以上是关于为啥是 IDisposable 接口? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Enumerable.Range 实现 IDisposable?

c# 中最简单的 IDisposable 模式是啥? [复制]

为啥 FxCop 坚持使用 IDisposable 作为结构

为啥 IDisposable 具有 [ComVisible(true)] 属性?

我应该何时实施 IDisposable? [复制]

PetaPoco.Database 实现了 IDisposable,那么为啥大多数示例没有“使用”语句呢?