0

这是一个典型的 IDispose 实现。我不明白的是析构函数?如果您班级的用户忘记调用 Dispose,由于析构函数不会调用 r1.Dispose(),您是否会发生资源泄漏?

public class DisposableObject : IDisposable
    {
        private bool disposed;
        private UnmanagedResource r1;

        public DisposableObject()
        {
            r1 = new UnmanagedResource();
        }

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


        public void Dispose()
        {

             this.Dispose(true);
             GC.SuppressFinalize(this);       
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    // clean up managed resources
                    //call dispose on your member objects
                    r1.Dispose();
                }

                // clean up unmanaged resources
                this.disposed = true;
            }
        }

        public void SomeMethod()
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }

        }
    }
4

6 回答 6

2

否 - 一旦对对象的所有引用都消失了,GC 将调用析构函数(但这不是确定性的)。

于 2013-02-13T21:59:36.583 回答
2

如果r1确实是本机资源(在您的示例中看起来不像),则不应在 if(disposing) 块内而是在它之后处理它。特别注意:

if (disposing) 
{
    // free managed resources
    if (managedResource != null)
    {
        managedResource.Dispose();
        managedResource = null;
    }
}
// free native resources if there are any.
if (nativeResource != IntPtr.Zero) 
{
    Marshal.FreeHGlobal(nativeResource);
    nativeResource = IntPtr.Zero;
}

正确实施 IDisposable - MSDN

如果r1是一个拥有自己实现的托管资源IDisposable,假设它被正确实现,任何本机资源都将在其终结器中正确清理(这就是为什么您不需要自己担心它的原因)。

于 2013-02-13T22:01:01.867 回答
0

析构函数(终结器)调用 Dispose 的原因是垃圾收集器在收集对象之前调用它,保证至少在某个时候 UnmanagedResource 将被释放。

通过使用usingtry...finally您可以强制资源在不需要时立即处置

http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx

于 2013-02-13T22:01:10.143 回答
0

如果你真的想,你可以添加一个终结器:

~DisposeImplementation()
{
    Dispose(false);
}

但它应该只用作真正的最后手段,而不是直接依赖的东西。

于 2013-02-13T22:02:49.580 回答
0

在 .Net 中,我们有一个称为垃圾收集的功能。垃圾收集最终确定所有未引用的对象(不再引用)。然后你的析构函数/终结器调用 Dispose()。

如果您的用户忘记删除这些引用,您最终会遇到某种泄漏。但这就是using目的:通过仅在要求范围内定义一次性用品来避免内存阻塞。

于 2013-02-13T22:04:10.870 回答
0

该模式的存在是因为垃圾收集器不保证托管对象被垃圾收集的顺序。因此,在终结器中,您不能保证r1引用仍然有效。

您的r1参考有一个类名,UnmanagedResource但它显然是一个托管类型。对于真正的无人资源,您将只有一个IntPtr或其他一些令牌。为了确保r1不喜欢它的资源,它应该实现相同的 Dispose 模式并在if (disposing)检查之外释放它的非托管资源。

于 2013-02-13T22:04:12.537 回答