IDisposable -正确的实现方式(c#)

本文关键字:方式 实现 IDisposable | 更新日期: 2023-09-27 18:16:13

我对何时以及如何实现IDisposable感到困惑。

我看到只需要为包含非托管资源的类实现IDIsposable

所以,如果我有类"A",持有非托管和托管的资源,我实现IDisposable的非托管资源,包括GC. suppressfinalize(这个),那么托管的资源将如何清理,如果GC现在不会调用我的类的终结器?

如果有人能让我更清楚地了解IDisposable(何时以及如何使用),我将不胜感激

IDisposable -正确的实现方式(c#)

这是错误的。您也可以为纯托管类实现iddispose。如果您只有托管资源,并且您的客户端没有调用Dispose,那么这些资源将在某个时候被垃圾收集器释放。但是,如果您确实希望更早地释放资源(例如,关闭文件或数据库连接),请在自己的Dispose方法中执行该操作。

你真的不应该为GC而烦恼。SuppressFinalize,除非你有终结器。如果你有一个定语器,尽量不要有它最好不要进入那个区域除非你绝对需要。

  • when part,非常简化:当你的类"拥有"(有时不那么明显)其他需要清理的IDisposable或非托管资源时,你应该实现IDisposable
  • how part:

    public class AClass : IDisposable 
    {
    public void Dispose() 
    {
        Dispose(true);
        GC.SuppressFinalize(this); 
    }
    protected virtual void Dispose(bool disposing)
    {
        if (disposing) 
        {
        // Free managed objects.
        }
        // Free unmanaged objects.
    }
    ~AClass() 
    {
     // Simply call Dispose(false).
         Dispose (false);
    }
    

    }

进一步阅读:
http://www.codeproject.com/KB/dotnet/IDisposable.aspx
http://blogs.msdn.com/b/kimhamil/archive/2008/11/05/when-to-call-dispose.aspx

IDisposable接口的独特之处在于,该语言实际上为它提供了一个特定的结构:"using"块:

public void SomeMethod()
{
    using(IDisposable myDisposable = new SomeClassThatImplementsIDisposable())
    {
        //Do something with your disposable...
    }
    //And, it's out of scope here
}

这是一个语法糖,实际上是这样的:

public void SomeMethod()
{
    IDisposable myDisposable = new SomeClassThatImplementsIDisposable();
    try 
    {    
        //Do something with your disposable...
    }
    finally
    {
        myDisposble.Dispose();
    }
    //And, it's out of scope here
}

因此,当您实现IDisposable时,您为类的客户提供了一种使用它的方法,他们可以确保(在大多数情况下)您打算为类进行的清理实际发生。

这在包含非托管资源的类中最为常见和关键。例如,如果您的类持有一个数据库连接,您不会希望客户机在没有关闭连接的情况下让它超出作用域,因为这将导致内存泄漏。上面的IDisposable用法还确保,如果生成了一些异常,"using()"所暗示的"finally"将调用您的dispose,以便您至少可以清理。

也就是说,在某些情况下,您可能会将其用于托管资源。首先想到的一个例子是,如果您的类的一个实例正在侦听由比您的类寿命更长的类的实例引发的事件。如果不进行处理,这也会造成内存泄漏(. net中的一个常见问题)。

所以,一般来说,如果你的类的一个实例超出了作用域而没有执行所有的清理代码,这将是很糟糕的情况,我会使用它。实现IDisposable向你的类的任何客户宣告,它拥有的资源需要被正确地处理。