Negative tive C # item18: Standard dispose Mode

Source: Internet
Author: User

If a type contains unmanaged resources, we should write our own method to release the unmanaged resources .. NET provides a standard mode for releasing resources, called the dispose mode. In this mode, the type implements the idisposable interface and provides a Terminator. In this way, users of the normal process call the dispose () method to release resources. If the user forgets to call the dispose () method, the type of Terminator is used as the final guarantee to release the unmanaged resources of the object.

In the dispose mode, the underlying class at the class level should implement the idisposable interface to release unmanaged resources, and a terminator should be added for this type as a safeguard mechanism. At the same time, both methods should finally make the method of releasing resources into a virtual method, so that the derived class can rewrite the virtual method to meet its resource management needs, only when a derived class must release its own resources, it must override the Virtual Methods in the base class and call the Virtual Methods of the base class.

When the Garbage Collector runs, it immediately releases the memory of the garbage objects without a Terminator. All objects that implement the terminator are still stored in the memory, but will be added to an ending queue. At the same time, the garbage collector will create a thread to run the Terminator on these objects, after the terminator thread completes its work, the memory of these junk objects can be completely deleted. In this way, the object to be terminated will stay in the memory longer than the object of the final terminal after the United States dollar.

When we implement the idisposable interface, we need to complete the following tasks in the dispose () method:

  1. Release all unmanaged resources.
  2. Release all managed resources.
  3. Set a status flag, indicating that the object has executed the dispose () method.
  4. To cancel the termination of an object, we can call GC. suppressfinalize (this.

In a hierarchy with full class inheritance, we can write the code for releasing resources of the base class as follows.

Code

  1 public class MyResourceHog : IDisposable
2 {
3 // Flag for already disposed
4   private bool _alreadyDisposed = false;
5
6 // finalizer:
7 // Call the virtual Dispose method.
8   ~MyResourceHog()
9 {
10 Dispose( false );
11 }
12
13 // Implementation of IDisposable.
14 // Call the virtual Dispose method.
15 // Suppress Finalization.
16   public void Dispose()
17 {
18 Dispose( true );
19 GC.SuppressFinalize( true );
20 }
21
22 // Virtual Dispose method
23   protected virtual void Dispose( bool isDisposing )
24 {
25 // Don't dispose more than once.
26   if ( _alreadyDisposed )
27 return;
28 if ( isDisposing )
29 {
30 // TODO: free managed resources here.
31   }
32 // TODO: free unmanaged resources here.
33 // Set disposed flag:
34   _alreadyDisposed = true;
35 }
36 }
37  

In the above Code, The Terminator and the dispose () method both have the need to release resources. Therefore, the code is extracted as a virtual method separately, in this way, if a derived class needs to release its own resources, you can override this method.

The subclass code is as follows.

Code

  1 public class DerivedResourceHog : MyResourceHog
2 {
3 // Have its own disposed flag.
4 private bool _disposed = false;
5
6 protected override void Dispose( bool isDisposing )
7 {
8 // Don't dispose more than once.
9 if ( _disposed )
10 return;
11 if ( isDisposing )
12 {
13 // TODO: free managed resources here.
14 }
15 // TODO: free unmanaged resources here.
16
17 // Let the base class free its resources.
18 // Base class is responsible for calling
19 // GC.SuppressFinalize( )
20 base.Dispose( isDisposing );
21
22 // Set derived class disposed flag:
23 _disposed = true;
24 }
25 }

Note: In the above Code, both the base class and the derived class contain a tag to set the release status of the object. This is a defense policy, which is used repeatedly in the class hierarchy, you can encapsulate "any possible errors during object release" in a type at the class level, rather than multiple types of the object. We need to do this because we may encounter calling the dispose () method after the instance is released. If an instance has been released, we need to call its dispose () method () method or the finalize () method should do nothing.

Note the following when writing the dispose () method or finalize () method:These methods should only release resources and should not contain other business logic.For an object, its lifecycle begins with the constructor and finally garbage collection. During the period when the object calls the dispose () method but the memory has not been deleted, we can think that the object is in a "coma" state. If we use the dispose () method, it is very likely that the object will be reset to available, which will disrupt the object's lifecycle.

Let's take a look at the following code.

Code

  1 public class BadClass
2 {
3 // Store a reference to a global object:
4 private readonly ArrayList _finalizedList;
5 private string _msg;
6
7 public BadClass( ArrayList badList, string msg )
8 {
9 // cache the reference:
10 _finalizedList = badList;
11 _msg = (string)msg.Clone();
12 }
13
14 ~BadClass()
15 {
16 // Add this object to the list.
17 // This object is reachable, no
18 // longer garbage. It's Back!
19 _finalizedList.Add( this );
20 }
21 }

In the destructor, the above Code puts the object itself into a list, so that the object itself becomes available, which is incorrect.

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.