Differences among Destructor Dispose and Close Methods in C

  • 2021-09-12 01:58:52
  • OfStack

1. The difference between Close and Dispose

After calling the Close method of the object, the object may be reused; For the Dispose method, the resources occupied by this object need to be marked as useless, that is, this object needs to be destroyed and can no longer be used. For example, the class SqlConnection in the common. Net class library can reopen a database connection through Open after calling Close method. When this object is completely used, you can call Dispose method to mark this object useless and wait for GC to recycle.

The difference between 2. 3 is shown in the figure

析构函数 Dispose方法 Close方法
意义 销毁对象 销毁对象 关闭对象资源
调用方式 不能被显示调用,在GC回收是被调用 需要显示调用或者通过using语句 需要显示调用
调用时机 不确定 确定,在显示调用或者离开using程序块 确定,在显示调用时

3. Description of destructor and Dispose

Dispose requires the implementation of the IDisposable interface.
Dispose is called by developer code, while the destructor is automatically called by GC.
The Dispose method should release all managed and unmanaged resources. The destructor should only release unmanaged resources. Because the destructor is called by GC, when GC judges that an object is no longer needed, it calls its destructor method, which may contain other useful managed resources.
Add the code "GC. SuppressFinalize (this)" at the end of the Dispose method. That is to say, GC does not need to call the destructor method of the object again, otherwise, GC will still call its destructor method after judging that the object is no longer useful. Although the program will not make mistakes, it will affect the system performance.
The destructor and Dispose should release the same resources, so that even if the class consumer does not call Dispose, the resources will be released in Finalize.
Finalize should not be public.
Releasing resources through frequent calls to destructor methods on the system GC will degrade system performance, so it is recommended to display calls to Dispose methods.
When an Dispose method exists, it should be called because Finalize is usually slow to release resources.

4. Description of the Close function

The Close method has different meanings in different classes, and there is no requirement that Close have special meanings, that is to say, Close does not have to release resources, and you can also make Close method mean "closed door". However, since Close means "off", Close is usually used to release resources, which is also allowed. For example, in file operation, it seems that releasing objects with Close is more accurate than Dispose, so when designing classes, you can set Close to public, set Dispose to protected, and then call Dispose from Close. That is to say, what Close means and whether it will release resources is entirely up to the class designer. It is one-sided to say on the Internet that "Close calls Dispose". In SqlConnection, Close only means closing the database connection, and does not release the object resource SqlConnection. As a rule of thumb, when Close and Dispose exist at the same time (both public), Close does not mean releasing resources, because in general, class designers should not use two public methods to release the same resources.

5. Examples of destructor and Dispose method

public class BaseResource : IDisposable
{
    // We said earlier that the destructor actually overrides the System.Object Virtual method in Finalize, By default ,1 Classes have no destructor , That is to say , Object is not called when it is garbage collected Finalize Method   
    ~BaseResource()
    {
        // In order to maintain the readability and maintainability of the code, , Never write code here to release unmanaged resources   
        // You must use the Dispose(false) Mode call , With false Tell Dispose(bool disposing) Function is obtained from the garbage collector when calling the Finalize Called when the   
        Dispose(false);
    }
    // Can't be called directly by customer   
    // If disposing Yes true, Then this method is called directly by the customer , So managed , And unmanaged resources can be released   
    // If disposing Yes false, Then the function is called from the garbage collector Finalize Called when the , You should not reference other managed objects at this time, so , Only unmanaged resources can be released   
    protected virtual void Dispose(bool disposing)
    {
        // Then this method is called directly by the customer , So managed , And unmanaged resources can be released   
        if (disposing)
        {
            // Release Managed resources   
            OtherManagedObject.Dispose();
        }
        // Release unmanaged resources   
        DoUnManagedObjectDispose();
        // Then this method is called directly by the customer , Tells the garbage collector to retrieve the Finalization Clear yourself from the queue , Preventing the garbage collector from calling Finalize Method .  
        if (disposing)
            GC.SuppressFinalize(this);
    }
    // Can be called directly by the customer   
    public void Dispose()
    {
        // You must use the Dispose(true) Mode call , With true Tell Dispose(bool disposing) The function is called directly by the client   
        Dispose(true);
    }
}

What the above example achieves:

1/If the customer does not invoke Dispose () and fails to release managed and unmanaged resources in time, there is still an opportunity to execute Finalize () and release unmanaged resources during garbage collection, but it causes idle waste of unmanaged resources that are not released in time

2/If the client invokes Dispose (), the managed and unmanaged resources can be released in time, then when the object is garbage collected, Finalize () will not be executed, which improves the use efficiency of unmanaged resources and improves the system performance

Finally:

If you use unmanaged resources in your class, consider providing Close methods, and Open methods. And call the Close method first in your Dispose method.

When using an existing class, such as SqlConnection. If you don't use this connection for the time being, you can consider using Close () method. If you don't use it, consider calling the Dispose () method.


Related articles: