请关于C#IDisposable的一些说明

Ron*_*ald 9 c#

我已经在不同的线程和不同的论坛中看到过很多次代码.特别是我从GC和IDispose如何在C#中工作?.

class MyClass : IDisposable
{
    ...

    ~MyClass()
    { 
        this.Dispose(false);
    }

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

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        { /* dispose managed stuff also */ }

        /* but dispose unmanaged stuff always */
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 是否有必要创建一个显式的析构函数?该类继承自IDisposable,在GC清理期间,最终将执行Dispose().

  2. Dispose(bool disposing)中参数'disposing'的意义是什么?为什么有必要区分托管和非托管对象的处理?

Jon*_*eet 5

垃圾收集器本身一无所知IDisposable.它不会为你配置任何东西 - 它所要做的就是调用终结器.

使用"disposing"参数进行重载的重点是终结器将调用Dispose(false)以指示它已从终结器调用,并且托管对象不需要任何清理,而如果您Dispose明确调用(例如通过using语句)最终会打电话Dispose(true).

这种模式的部分重点在于它对于派生类是可扩展的 - 只有基类终结器需要调用Dispose,而其他所有内容都会在Dispose(bool)必要时通过覆盖来捎带.

但是,除非您实际上可以直接访问非托管资源 - 或者期望派生类 - 否则您可能根本不需要终结器.如果您确实需要相当直接的访问,那么SafeHandle有助于避免编写终结器.这几天几乎不需要写一个终结器.我个人很少实现IDisposable自己,当我这样做时,通常来自一个密封的类(因为我喜欢在可能的情况下密封类) - 它几乎从不涉及终结器...所以我只写一个Dispose方法来实现接口并离开就在那.更简单.

在您可以想象的每种情况下实施完整建议IDisposable是非常冗长和复杂的.我认为尽可能将自己局限于更简单的情况是值得的.


Mar*_*ell 2

1:没有;这仅在直接包装外部非托管资源的类中常见,例如 windows-handles;或者如果某个子类可能会这样做。如果您只处理托管对象,那么添加终结器实际上是一件坏事,因为它会影响 wat 集合的工作

2:它告诉Dispose(bool)代码当前是否处于垃圾回收中(如果是false)。被收集时,您不应该触摸自己以外的任何其他物品,因为它们可能已经消失了。然而,如果您被选择性地处置(即true),您可能需要清理一些封装的托管对象;例如,调用.Close()您正在包装的连接