在实现IDisposable接口之后,是否需要从类的析构函数中调用Dispose方法? [英] Do we need to call Dispose method from the destructer of the class after implmenting IDisposable interface?

查看:49
本文介绍了在实现IDisposable接口之后,是否需要从类的析构函数中调用Dispose方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们是否需要在下面的代码中从类的析构函数调用Dispose方法?

Do we need to call the Dispose method from the destructer of the class in the below code?

public class SimpleCleanup : IDisposable
{
    // some fields that require cleanup
    private SafeHandle handle;
    private bool disposed = false; // to detect redundant calls

    public SimpleCleanup()
    {
        this.handle = /*...*/;
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                if (handle != null)
                {
                    handle.Dispose();
                }
            }

            disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }
}

推荐答案

是的,您应该:
Yes, you should: Implementing Finalize and Dispose to Clean Up Unmanaged Resources[^]


您的意思是说要重写Finalize方法.

在上述实现中,您可以从Finalize/Destructor中使用False调用Dispose方法.

原因是GC正在处理Dispose方法,而析构函数则是无法在Dispose方法中释放的资源的备份计划.

因此,在上面的代码中,当您从析构函数将false传递给Dispose时,代码将检查对象是否已被处置.并且基于标志,它应该决定对象是否需要处置.

这是用于处置对象的隐式清理.

谢谢,
Rushikesh Joshi
You mean to say overriding Finalize method.

In above implementation you can call Dispose method with False from Finalize/Destructor.

Reason is GC is taking care of Disposing an object and destructor is kind of backup plan for resources which were not able to released in Dispose method.

So in above code when you pass false to Dispose from destructor, code will check whether object has already been disposed or not. And based on flags it should decide object need to dispose or not.

This is for implicit cleanup for disposing object.

Thanks,
Rushikesh Joshi


我认为在上述情况下我们不需要调用Dispose方法.请看下面的代码库.仅当您要处置非托管对象时,才需要从类的析构函数中调用Dispose(false).


I dont think we need to call the Dispose method in the above scenario. Please take a look at the below code base. We need to call the Dispose(false) from the destructer of the class only if you want dispose unmanaged objects.


using System;
using System.ComponentModel;

// The following example demonstrates how to create
// a resource class that implements the IDisposable interface
// and the IDisposable.Dispose method.

public class DisposeExample
{
    // A base class that implements IDisposable.
    // By implementing IDisposable, you are announcing that
    // instances of this type allocate scarce resources.
    public class MyResource: IDisposable
    {
        // Pointer to an external unmanaged resource.
        private IntPtr handle;
        // Other managed resource this class uses.
        private Component component = new Component();
        // Track whether Dispose has been called.
        private bool disposed = false;

        // The class constructor.
        public MyResource(IntPtr handle)
        {
            this.handle = handle;
        }

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if(disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }

                // Call the appropriate methods to clean up
                // unmanaged resources here.
                // If disposing is false,
                // only the following code is executed.
                CloseHandle(handle);
                handle = IntPtr.Zero;

                // Note disposing has been done.
                disposed = true;

            }
        }

        // Use interop to call the method necessary
        // to clean up the unmanaged resource.
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private extern static Boolean CloseHandle(IntPtr handle);

        // Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~MyResource()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
        }
    }
    public static void Main()
    {
        // Insert code here to create
        // and use the MyResource object.
    }
}


这篇关于在实现IDisposable接口之后,是否需要从类的析构函数中调用Dispose方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆