简体   繁体   English

C#处理模式

[英]c# Dispose pattern

Here is a typical IDispose implementation. 这是典型的IDispose实现。 What I don't understand is the destructor? 我不了解的是析构函数? If the user of your class forgets to call Dispose, wouldn't you have a resource leak since the destructor will not call r1.Dispose()? 如果您的类的用户忘记了调用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);
            }

        }
    }

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

If r1 is truly a native resource (which it doesn't look like it in your example), it should not be disposed of inside the if(disposing) block but after it. 如果r1确实是本机资源(在您的示例中看起来不是本机资源),则不应将其丢弃在if(dispose)块内,而应放在它之后。 Pay particular attention to: 请特别注意:

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;
}

From Implement IDisposable Correctly - MSDN 正确实现IDisposposable-MSDN

If r1 is a managed resource with its own implementation of IDisposable , assuming it is implemented properly, any native resources will be cleaned up properly in its finalizer (which is why you don't need to worry about it in your own). 如果r1是具有自己的IDisposable实现的托管资源(假设其实现正确),则将在其终结器中正确清理任何本机资源(这就是为什么您不必自己担心它)。

The reason for the destructor (finalizer) to call Dispose is because Garbage Collector calls it before it collects an object, guaranteeing that at least at some point the UnmanagedResource will be freed. 析构函数(finalizer)调用Dispose的原因是因为垃圾收集器在收集对象之前对其进行了调用,从而确保至少在某个时候可以释放UnmanagedResource。

By using using and try...finally you can enforce the resource to be disposed as soon as they are not needed 通过usingtry...finally可以强制资源尽快不需要他们布置

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

If you really want to, you can add a finalizer: 如果确实需要,可以添加一个终结器:

~DisposeImplementation()
{
    Dispose(false);
}

But it should only be used as a true last resort, not something to rely on directly. 但是,它只能用作真正的不得已的手段,而不能直接依赖。

In .Net, we have a feature called Garbage Collection. 在.Net中,我们有一个称为垃圾收集的功能。 Garbage Collection finalizes all Objects that are not referenced (any more). 垃圾回收将最终确定所有未引用的对象(不再)。 Your Destructor / finalizer then calls Dispose(). 然后,您的析构函数/终结器将调用Dispose()。

If your user forgets to remove those references, you will end up with sort-of a leak. 如果您的用户忘记删除这些引用,则最终会导致某种形式的泄漏。 But that's what using is for : avoid memory blockage by defining your disposables only in the scope of requirement. 但是,这就是using是:避免内存阻塞仅在要求的范围定义您的一次性。

The pattern exists because the garbage collector does not guarantee the order that managed objects will be garbage collected. 之所以存在该模式,是因为垃圾收集器无法保证垃圾收集被管理对象的顺序。 So in the finalizer you are not guaranteed that the r1 reference is still valid. 因此,在终结器中,不能保证r1引用仍然有效。

Your r1 reference has a class name of UnmanagedResource but it is clearly a managaged type. 您的r1引用的类名称为UnmanagedResource但显然是被管理的类型。 For a real unmanned resource you would only have an IntPtr or some other token. 对于真正的无人资源,您将只有一个IntPtr或其他令牌。 To ensure that r1 does non like it's resource it should implement the same Dispose pattern and free it's unmanaged resource outside of the if (disposing) check. 为了确保r1不会像它的资源那样使用它,它应该实现相同的Dispose模式,并在if (disposing) dispose if (disposing)检查之外释放它的非托管资源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM