2011-12-01 92 views
1

我很困惑什么时候以及如何实现IDisposable。IDisposable - 正确的方法实现(c#)

我看到它需要实现IDisposable只对持有非托管资源

因此类,如果我有“A”级持有unmanged和管理资源,我实现IDisposable非托管资源,包括GC.SuppressFinalize(这个),那么如果GC现在不会为我的班级调用finializer,管理资源将如何清理?

我真的会如并欣赏别人可以了IDisposable我更加清晰(何时以及如何使用)

+2

这里的职位是非常明确的=> http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface – StuartLC

+0

感谢!我会读这个 – Maya

回答

1

这是不正确。您也可以为受管理类实施IDispose。如果您只有托管资源,并且您的客户端不调用Dispose,则资源将在某个时刻被垃圾回收器释放。但是,如果您希望更早释放资源(例如关闭文件或数据库连接),请在您自己的Dispose方法中执行此操作。

除非你有一个终结器,否则你不应该用GC.SuppressFinalize。如果你有一个终结者,尽量不要有 - 最好不要进入该地区,除非你绝对必须。

+0

我在MSDN看到GC对它的托管资源要好得多。即使我没有终结器明确我的课程仍然有一个(如果不是如何GC调用终结?)。也是文件和数据库他们不unmanged? – Maya

+0

@Maya - 对于您没有花费昂贵资源的托管资源,GC更好。这几乎意味着只有占用相对少量内存的类。对于消耗昂贵或竞争资源的托管类,如文件或线程或网络连接,即使该类是纯粹管理的,您也会希望尽快释放您确定性的用法。 – codekaizen

0

有关IDisposable接口的唯一的事情是,语言实际上提供了它的特殊结构:“使用”块:

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广告给您的班级的任何客户,有资源,它认为需要妥善处置。

+0

我会为类对象保留术语“托管资源”,如果这些对象被抛弃并且它们的代码被垃圾收集,它们将执行任何清理责任,但是如果处置完成,它们将更快地执行它们。我认为长期出版商附带的活动订阅是非托管资源,因为在放弃活动订阅者之后可以执行任意数量的第2级集合,并且如果发布者仍在范围之内,订阅者将永远不符合资格采集。请注意...... – supercat

+0

...事件订阅在一些现实和合理的情况下可以很容易地表示一个无限的内存泄漏。例如,IEnumerator可能会订阅已更改集合的事件。如果集合在其生命周期中枚举了10万次(几乎不可信),则可能导致附加100,000个订阅。除了许多事件订阅会扼杀系统之外,即使是一百万枚枚举也不会令人难以置信。 – supercat

1
  • 时的一部分,很简单:你应该实现IDisposable时,你的类“拥有”(这是不那么obviuos有时),这需要进行清除IDisposable的或者非托管资源
  • 如何部分:

    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