[to] improve C # program recommendations 4:c# the implementation of the standard Dispose mode

Source: Internet
Author: User

You need to be clear about C # programs (or. NET) resources. In a nutshell, each of the types in C # represents a resource, and resources fall into two categories:

Managed resources: Resources allocated and freed by the CLR, which are objects that are made by new in the CLR;

Unmanaged resources: Objects that are not managed by the CLR, Windows kernel objects such as files, database connections, sockets, COM objects, and so on;

Without exception, if our type uses unmanaged resources, or if we need to explicitly dispose of managed resources, then you need to have the type inherit the interface IDisposable. This is equivalent to telling the caller that the type is required to explicitly dispose of the resource, and you need to call my Dispose method.

However, this is not so simple, a standard inherits the type of IDisposable interface should be implemented as follows. This implementation we call the Dispose pattern:

publicclass sampleclass:idisposable {//Demo Creating an unmanaged resourcePrivateIntPtr Nativeresource = Marshal.allochglobal ( -); //Demo Creating a managed resourcePrivateAnotherresource Managedresource =NewAnotherresource (); Privatebool disposed=false; ///<summary>        ///implementing the Dispose method in IDisposable///</summary>publicvoid Dispose () {//must be TrueDispose (true); //notifies the garbage collection mechanism not to call finalizers (destructors)Gc. SuppressFinalize ( This); }        ///<summary>        ///not necessary, provide a close method just to be more compliant with other languages (such as C + +) specification///</summary>publicvoid Close () {Dispose (); }        ///<summary>        ///must, in case the programmer forgets to explicitly call the Dispose method///</summary>~SampleClass () {//must be falseDispose (false); }        ///<summary>        ///protected virtual for non-sealed class modification///Seal class decoration with private///</summary>        ///<param name= "disposing" ></param>Protectedvirtualvoid Dispose (BOOLdisposing) {            if(disposed) {return; }            if(disposing) {//clean up Managed resourcesif(Managedresource! =NULL) {managedresource.dispose (); Managedresource=NULL; }            }            //Cleanup of unmanaged Resourcesif(Nativeresource! =IntPtr.Zero) {Marshal.freehglobal (Nativeresource); Nativeresource=IntPtr.Zero; }            //let the type know that they have been releaseddisposed =true; } publicvoid Samplepublicmethod () {if(disposed) {thrownew ObjectDisposedException ("SampleClass","SampleClass is disposed"); }            //omitted        }    }

In Dispose mode, almost every line has a special meaning.

In the standard dispose mode, we notice a method that begins with a ~:

/// <summary>        /// must, in case the programmer forgets to explicitly call the        Dispose method /// </summary>~sampleclass ()        {            // must be false            Dispose ( false );        }

This method is called a type terminator. The whole point of providing a finalizer is that we cannot expect the caller of the type to be actively invoking the Dispose method, based on the fact that the finalizer is called by the garbage collector, and the finalizer is used as a remedy for resource release.

A type of Dispose method should allow multiple calls without throwing exceptions. For this reason, the type internally maintains a private Boolean variable disposed:

private bool disposed = false;

In the actual method of handling code cleanup, add the following judgment statement:

if (disposed) {return;} // omit the code for the Cleanup section and assign a value of disposed to truedisposed =trueat the end of the method.

This means that if a type is cleaned up once, the cleanup will no longer work.

It should be noted that in the standard Dispose mode, the Dispose method that really implements the IDisposable interface does not have actual cleanup work, it actually calls the following protected virtual method with a Boolean parameter:

/// <summary>        /// protected virtual        for non-sealed class modification /// Seal class decoration with private         /// </summary>        /// <param name= "disposing" ></param>        Protectedvirtualvoid Dispose (bool  disposing)        {            // omit code        }

The reason for providing such a protected virtual method is to take into account the fact that this type is inherited by other classes. If a type has a subclass, the subclass might implement its own dispose pattern. A protected virtual method is used to remind subclasses that they must notice the cleanup of the parent class when implementing their own cleanup method, that is, the subclass needs to call base in its own release method. Dispose method.

Also, we should have noticed that the virtual method that actually writes the resource release code is with a Boolean parameter. This parameter is provided because we treat managed and unmanaged resources differently when the resource is released.

The call parameter is true in the parameterless Dispose method for the explicitly freed resource that is called by the caller:

publicvoid Dispose () {// must be true forDispose (true); // other ellipsis }

This indicates that the code should handle both the managed and unmanaged resources at this time.

In the finalizer for an implicit cleanup resource that is called by the garbage collector, the calling parameter is false:

~SampleClass () {// must be falseDispose (false);}

This indicates that when an implicit cleanup is available, the unmanaged resources are processed as long as they are handled.

So why treat managed and unmanaged resources differently. Before we elaborate on this, we need to understand first: does the managed resource need to be cleaned up manually? You might want to first divide the types in C # into two categories, one inheriting the IDisposable interface, and one without inheritance. The former, which we call a non-trivial type for the time being, is called the normal type. Non-trivial type because it contains an unmanaged resource, it needs to inherit the IDisposable interface, but this contains the unmanaged resource's type itself, which is a managed resource. So does the managed resource need to be cleaned up manually? The answer to this question is that the normal type in the managed resource does not need to be cleaned manually, rather than the normal type, which needs to be cleaned manually (that is, the Dispose method is called).

The idea of the Dispose pattern design is based on: if the caller explicitly calls the Dispose method, then the type should be programmed to release all resources. If the caller forgets to call the Dispose method, then the type assumes that all of its managed resources (even those of the non-trivial type described in the previous paragraph) are all handed over to the garbage collector for recycling without manual cleanup. With this in mind, we understand why the parameter passed by the virtual method in the Dispose method is true, and the parameter passed in by the virtual method is false in the finalizer.

Note: We mentioned the need to release resources in a timely manner without further elaborating on the need to make the reference equal to NULL in a timely manner. Some people think that equal to NULL can help the garbage collection mechanism to discover and identify objects as garbage earlier. Others thought it was no help. Next article, "Assignment of reference types to null and accelerated garbage collection" Let us dwell on this point.

Citation connections:

Recommendations for improving C # programs implementation of the standard Dispose pattern in 4:c#

[to] improve C # program recommendations 4:c# the implementation of the standard Dispose mode

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.