Dispose and Finalize in Dot Net OR Maemory Management using Dispose and Finalize

       Dotnet provides automatic memory managenet using Dispose and Fibnalize method. You will find this in classes that acquire and hold on to resources such as file and window handles or network and database connections. This is the case because the Common Language Runtime (CLR) within which your .NET code runs implements nondeterministic finalization, meaning that the CLR ultimately decides when object instances are no longer able to be referenced and when those instances are deallocated in memory. The process of reclaiming memory by deallocating instances is referred to as garbage collection, or simply GC.

       Lets  have a look at Finalize method first and then we will look in to the Dispose method. Finalize method is implicitly called by GC when object reference is no longer available. C# user can not call Finalize method. There is no way to call finalize method using code in C#. VB.net developer can do !!!! When user creates a desructor for a class CLR will generates the Finalize method for that class. Look at the code below,

public class Base
{

          // Use C# destructor syntax for finalization code.
          ~Base()
         {
                // Simply call Dispose(false).
         }
}

Fig – (1) A class with Destructor

       Above code shows Base class which has a destructor. So when the object of this class is no longer referenced the destroctur will be called. Now the question is this is destructor where is Finalize method ? You can get your answer when you see the IL generated by this code.

 Fig – (2) IL generated for Destructor (~Base())

        You can see that CLR has generated finalize method for destructor. Method has try and finally block.  The code written in destructor by user is inside the try block and finally block contains call to finalize method of System.Object class which is a base class of all the classes in dotnet.

        Finalize is protected and, therefore, is accessible only through this class or a derived class.

        This method is automatically called after an object becomes inaccessible, unless the object has been exempted from finalization by a call to SuppressFinalize. During shutdown of an application domain, Finalize is automatically called on objects that are not exempt from finalization, even those that are still accessible. Finalize is automatically called only once on a given instance, unless the object is re-registered using a mechanism such as ReRegisterForFinalize and GC.SuppressFinalize has not been subsequently called.

         Every implementation of Finalize in a derived type must call its base type’s implementation of Finalize. This is the only case in which application code is allowed to call Finalize.

         Finalize operations have the following limitations:

  • The exact time when the finalizer executes during garbage collection is undefined. Resources are not guaranteed to be released at any specific time, unless calling a Close method or a Dispose method.
  • The finalizers of two objects are not guaranteed to run in any specific order, even if one object refers to the other. That is, if Object A has a reference to Object B and both have finalizers, Object B might have already finalized when the finalizer of Object A starts.
  • The thread on which the finalizer is run is unspecified.

         The Finalize method might not run to completion or might not run at all in the following exceptional circumstances:

  • Another finalizer blocks indefinitely (goes into an infinite loop, tries to obtain a lock it can never obtain and so on). Because the runtime attempts to run finalizers to completion, other finalizers might not be called if a finalizer blocks indefinitely.
  • The process terminates without giving the runtime a chance to clean up. In this case, the runtime’s first notification of process termination is a DLL_PROCESS_DETACH notification.

         The runtime continues to Finalize objects during shutdown only while the number of finalizable objects continues to decrease.

          If Finalize or an override of Finalize throws an exception, the runtime ignores the exception, terminates that Finalize method, and continues the finalization process.

Summary

          A type must implement Finalize when it uses unmanaged resources such as file handles or database connections that must be released when the managed object that uses them is reclaimed. See the IDisposable interface for a complementary and more controllable means of disposing resources.

          Finalize can take any action, including resurrecting an object (that is, making the object accessible again) after it has been cleaned up during garbage collection. However, the object can only be resurrected once; Finalize cannot be called on resurrected objects during garbage collection.

          [C#] Destructors are the C# mechanism for performing cleanup operations. Destructors provide appropriate safeguards, such as automatically calling the base type’s destructor. In C# code, Object.Finalize cannot be called or overridden.

 

Dispose

          Lets talk about dispose now. As desribe above CLR implicitly calls Finalize method. However what if user explicitly wants to realease the resources used by object. Here the Dispose the method comes in to the picture. 

          A type’s Dispose method should release all the resources that it owns. It should also release all resources owned by its base types by calling its parent type’s Dispose method. The parent type’s Dispose method should release all resources that it owns and in turn call its parent type’s Dispose method, propagating this pattern through the hierarchy of base types. To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.

           A Dispose method should call the GC.SuppressFinalize method for the object it is disposing. If the object is currently on the finalization queue, GC.SuppressFinalize prevents its Finalize method from being called. Remember that executing a Finalize method is costly to performance. If your Dispose method has already done the work to clean up the object, then it is not necessary for the garbage collector to call the object’s Finalize method.

         See the sample code for implementation of Dispose method.

public class Base : IDisposable
{
         //Implement IDisposable.
        public void Dispose()
        {
               Dispose(true);
               GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
       {
               if (disposing)
               {
                       // Free other state (managed objects).
               }
               // Free your own state (unmanaged objects).
               // Set large fields to null.
       }

       // Use C# destructor syntax for finalization code.
      ~Base()
      {
               // Simply call Dispose(false).
               Dispose(false);
      }
}

// Design pattern for a derived class.
public class Derived : Base
{
       protected override void Dispose(bool disposing)
       {
                if (disposing)
                {
                         // Release managed resources.
                }
                // Release unmanaged resources.
               // Set large fields to null.
              // Call Dispose on your base class.
              base.Dispose(disposing);
       }
       // The derived class does not have a Finalize method
       // or a Dispose method with parameters because it inherits
       // them from the base class.
}

Fig – (3) Dispose pattern for Base and derived class.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值