c#处理模式

时间:2013-02-13 21:55:07

标签: c# idisposable

这是典型的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);
            }

        }
    }

6 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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;
}

来自Implement IDisposable Correctly - MSDN

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

答案 2 :(得分:0)

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

通过使用usingtry...finally,您可以强制执行资源,以便在不需要时立即处理

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

答案 3 :(得分:0)

如果您真的想要,可以添加终结器:

~DisposeImplementation()
{
    Dispose(false);
}

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

答案 4 :(得分:0)

在.Net中,我们有一个名为垃圾收集的功能。垃圾收集完成所有未引用的对象(任何更多)。你的析构函数/终结器然后调用Dispose()。

如果您的用户忘记删除这些引用,您最终会发生泄漏。 但这就是using的用途:通过仅在需求范围内定义一次性用品来避免内存堵塞。

答案 5 :(得分:0)

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

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