2

我最近不得不实现 Dispose() 功能,并且遇到了 1 行方法、2 行方法和更全面的方法。

1 行方法/函数会简单地调用类似“context.Dispose”的东西,但我选择的方法是这样的:

    bool _disposed = false;

    public void Dispose(bool disposing)
    {
        if (!_disposed && disposing)
        {
            _context.Dispose();
        }
        _disposed = true;
    }

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

这种语法仅仅是为了阻止 Dispose() 被多次调用吗?

4

3 回答 3

4

您发布的部分内容是Dispose Pattern。正如有人指出的那样,Dispose(false)终结器(“析构函数”)中应该有对应的。终结器应该用于处理非托管资源。如果您没有要处理的非托管资源(即当disposingis时false您无事可做),则不需要 a Dispose(false),因此也不需要终结器。这意味着这Dispose(true)是唯一的路径,因此您不需要Dispose (bool)(因此不需要实现 Dispose 模式)并且可以将它的主体移动到Dispose(并删除对 的检查disposing)并且只需实现Dispose. 例如:

public void Dispose()
{
    _context.Dispose();
}

没有实现自己的终结器(析构函数)的类不会放在终结器列表中,因此无需调用GC.SuppressFinalize.

一般来说,如果你正在创建一个类,这就足够了。但是,有时您可以从实现此模式的类派生。在这种情况下,您应该在您的类中实现对它的支持(覆盖Dispose(bool)disposing检查Dispose任何托管资源)。由于基IDisposable类在virtual Dispose(bool)Dispose()的. 例如:Dispose()Dispose(bool)Dispose(bool)

protected override void Dispose(bool disposing)
{
    if(disposing) _context.Dispose();
    base.Dispose(disposing);
}

如果您正在调用基础并且它实现了 Dispose 模式,那么您也不需要调用GC.SuppressFinalize(),因为它已经在执行它。

如果你愿意,你可以做所有的disposed事情;我发现它虽然隐藏了多重处理错误。

于 2012-08-26T14:28:42.587 回答
2

这只是模式的一部分。这里缺少的另一部分Dispose(false)将由终结器调用。

_disposed状态标志也可以用来检查和抛出你的ObjectDisposedExceptions方法。

完整的模式在这里

Jon Skeet在这里提供了很好的信息,而且 IMO 这种模式在大多数情况下都是多余的,除非您还有非托管资源。如果没有,只需GC.SuppressFinalizeDispose()接口实现中处理您的托管资源。_disposed仅当您打算投掷时才使用该标志ObjectDisposedExceptions

于 2012-08-26T13:02:38.070 回答
1

我根据类需要使用以下两种形式的 dispose:

方法 1(对于具有托管和非托管资源或具有派生类的类):

class ClassHavingManagedAndUnManagedCode : IDiposable
    {
        private volatile bool _disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    //Do managed disposing here.
                }

                //Do unmanaged disposing here.
            }
        }

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

            _disposed = true;
        }

        ~ClassHavingManagedAndUnManagedCode()
        {
            Dispose(false);
        }
    }

方法2(对于只有托管资源的类/密封类/没有子类的类):

    class ClassHavingOnlyManagedCode  : IDiposable
    {
        private volatile bool _disposed = false;

        public void Dispose()
        {
            if (!_disposed)
            {
                //Dispose managed objects.
                _disposed = true;
            }
        }
    }

ClassHavingManagedAndUnManagedCode 的任何子类都应该遵循受保护的 dispose 方法模式,并在 Dispose 方法的末尾调用 base.Dispose。

还要保护所有公共方法(至少使用已释放成员的方法),如果类实例已被释放,则使用抛出 ObjectDisposedException 的方法 /check。

即使您没有任何非托管资源,FxCop 也会始终要求您实现 Dispose 的 ClassHavingManagedAndUnManagedCode 形式。

于 2012-08-26T13:11:08.873 回答