Finalize() and Dispose()

C# provides special methods that are used to release the instance of a class from memory, Finalize() and Dispose().

Finalize()

  • The Finalize method is used to perform cleanup operations on unmanaged resources held by the current object before the current object is destroyed.
  • In C# destructor are converted to finalize method by C# compiler.
  • The scope of the Object.Finalize method is protected.
  • The Finalize() destructor is called after the last reference to an object is released from the memory.
  • It is automatically called by garbage collector to release resource.
  • The exact time when the finalizer executes during garbage collection is undefined.
Illustrate by an example

Create a class FinalizeImplement which has a destructor ~FinalizeImplement()

using System;
using System.Diagnostics;

namespace CSharp
{
    class FinalizeImplement
    {
        Stopwatch sw;

        public FinalizeImplement()
        {
            sw = Stopwatch.StartNew();
            Console.WriteLine("Instantiated object");
        }

        public void ShowDuration()
        {
            Console.WriteLine("This instance of {0} has been in existence for {1}",this, sw.Elapsed);
        }

        ~FinalizeImplement()
        {
            Console.WriteLine("Finalizing object");
            sw.Stop();
            Console.WriteLine("This instance of {0} has been in existence for {1}", this, sw.Elapsed);
            Console.ReadLine();
        }
    }    
}

Create a program in which implemented finalize

namespace CSharp
{   
    class Program
    {
        static void Main(string[] args)
        {
            FinalizeImplement objFinalize = new FinalizeImplement();
            objFinalize.ShowDuration();

        }
    }
}
OUTPUT
finalize()

finalize()

Dispose()

  • The Dispose() method is called to release a resource, such as a database connection, as soon as the object using such a resources is no longer in use.
  • It is not automatically and you must explicitly call it from client application when an object is no longer needed.
  • The IDisposable interface contains the Dispose() method.
  • 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.
  • Use this method to close or release unmanaged resources such as files, streams, and handles held by an instance of the class that implements this interface.
Illustrate by an example

Create a class DisposableResource. This class shows how to use a disposable resource. The resource is first initialized and passed to the constructor, but it could also be initialized in the constructor. The lifetime of the resource does not exceed the lifetime of this instance.This type does not need a finalizer because it does not directly create a native resource like a file handle or memory in the unmanaged heap.

using System;
using System.IO;

namespace DisposeExample
{
    public class DisposableResource : IDisposable
    {
        private Stream mResource;
        private bool mDisposed;

        // The stream passed to the constructor must be readable and not null. 
        public DisposableResource(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("Stream in null.");
            }
            if (!stream.CanRead)
            {
                throw new ArgumentException("Stream must be readable.");
            }

            mResource = stream;
            mDisposed = false;
        }

        // Demonstrates using the resource. It must not be already disposed. 
        public void GetResourceSize()
        {
            if (mDisposed)
            {
                throw new ObjectDisposedException("Resource was disposed.");
            }

            // Show the number of bytes. 
            int numBytes = (int)mResource.Length;
            Console.WriteLine("Number of bytes: {0}", numBytes.ToString());
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        //Disposing resource if its not already dispose
        protected virtual void Dispose(bool disposing)
        {
            // If you need thread safety, use a lock around these operations, as well as in your methods that use the resource. 
            if (!mDisposed)
            {
                if (disposing)
                {
                    if (mResource != null)
                    {                                              
                        mResource.Dispose();                        
                    }
                    Console.WriteLine("Object disposed.");
                }

                // Indicate that the instance has been disposed.
                mResource = null;
                mDisposed = true;
            }
        }
    }
}

Create a program in which implemented dispose

using System;
using System.IO;

namespace DisposeExample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // Initialize a Stream resource to pass to the DisposableResource class.
                Console.Write("Enter filename with full path: ");
                string fileSpecification = Console.ReadLine();
                FileStream fStream = File.OpenRead(fileSpecification);
                DisposableResource objDisposableResource = new DisposableResource(fStream);

                // Use the resource.
                objDisposableResource.GetResourceSize();

                // Dispose the resource.
                objDisposableResource.Dispose();
                Console.Read();
            }
            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}
OUTPUT

Dispose()

Dispose()

Delegate

A delegate is an object that can refer to a method. Thus, when we create a delegate, we are creating an object that can hold a reference to a method. Furthermore, the method can be called through this reference. Thus, a delegate can invoke the method to which it refers.

The principal advantage of a delegate is that it allows us to specify a call to a method, but the method actually invoked is determined at runtime, not at compile time.

Some Features:

  1. Delegates can be declared either outside a class definition or as part of a class through the use of the delegate keyword.
  2. Delegates have two parts in the relationship: the delegate declaration and the delegate instance or static method.
  3. If an exception is thrown, the delegate stops processing methods in the invocation list. It does not matter whether or not an exception handler is present.
  4. The keyword delegate and the .NET infrastructure provided by the System.Delegate (all delegate types are derived) and System.Delegate.MulticastDelegate classes.
  5. Delegates are the heart and soul of event handling in .NET.
  6. It is a compile-time error for the same modifier to appear multiple times in a delegate declaration.
  7. Delegate types are implicitly sealed.

(A). Simple Delegate
Declaration of delegate:
delegate-modifier delegate return-type delegate-name(parameters)
Implementation of delegate:
Delegate-name delegate-object=new Delegate-name(method of class)
Illustration with an Example:

using System;
namespace SimpleDelegate
{
    public delegate int AddNumber(int i,int j);
    public class ImplementDelegate
    {
        public int Add(int i, int j)
        {
            return i + j;
        }
    }
    class Program
    {       
        static void Main(string[] args)
        {
            int sum=0;
            ImplementDelegate objimp = new ImplementDelegate();
            AddNumber d = new AddNumber(objimp.Add);
            sum=d(12, 13);
            Console.WriteLine("Addition of 12 and 13 is " + sum);
            Console.Read();
        }
    }
}

Out Put:
Delegate in C#

(B) MulticastDelegate

One of the most exciting features of a delegate is its support for multicasting. In simple terms, multicasting is the ability to create a chain of methods that will be called automatically when a delegate is invoked. Simply instantiate a delegate, and then use the + or += operator to add methods to the chain. To remove a method, use – or – =. If the delegate returns a value, then the value returned by the last method in the list becomes the return value of the entire delegate invocation. For this reason, a delegate that will make use of multicasting will often have a void return type.

Illustration with an Example:

using System;
namespace DelegateExample
{
   public delegate void MyDelegate(int i);
    public class DelegateImplement
    {
        public void ClassMethod(int i)
        {
            Console.WriteLine("Value of i in ClassMethod:{0}", i);
        }

        public static void StaticClassMethod(int i)
        {
           Console.WriteLine("Value of i in StaticClassMethod:{0}",i);
        }
        public void AnotherClassMethod(int i)
        {
           Console.WriteLine("Value of i in AnotherClassMethod:{0}",i);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            DelegateImplement objimp = new DelegateImplement();

            MyDelegate d = new MyDelegate(objimp.ClassMethod);
            d(10);
            Console.WriteLine();
            d += new MyDelegate(DelegateImplement.StaticClassMethod);
            d(12);
            Console.WriteLine();
            d += new MyDelegate(objimp.AnotherClassMethod);
            d(15);
            Console.Read();
        }
    }
}

Output:Example of Delegate in C#

Ref Versus Out keyword

(A) Ref Keyword

  1. When a parameter pass with ref keyword in function then function work with same variable value that is passed in function call. If variable value change then function parameter value also change.
  2. Both the function definition and function calling must explicitly use the ref keyword.
  3. In function call argument passed to a ref parameter must first be initialized.
  4. ref parameter variable should not be declare as a constant variable.
  5. It is not compulsory that ref parameter name should be same in both function definition and function call.

Illustration with an Example

using System;
    class Program
    {
        static void Add(ref int val)
        {
            val += 12;
            Console.WriteLine("Number in Method : {0}", val);
        }
        static void Main(string[] args)
        {
            int number = 13;
            Console.WriteLine("Number before Method call:{0}",number);
            Add(ref number);
            Console.WriteLine("Number after Method call:{0}",number);
            Console.Read();
        }
    }

Output:
Ref keyword output

(B) Out Keyword

  1. When a parameter pass with out keyword in function then function work with same variable value that is passed in function call. If variable value change then function parameter value also change.
  2. Both the function definition and function calling must explicitly use the out keyword.
  3. It is not necessary to initialize out parameter variable that is pass in function call.
  4. out parameter variable should not be declare as a constant variable.
  5. It is not compulsory that out parameter name should be same in both function definition and function call.

Illustration with an Example

using System;
    class Program
    {
        static void Add(out int val)
        {
            val = 12;
            val += 13;
            Console.WriteLine("Number in Method call:{0}",val);
        }
        static void Main(string[] args)
        {
            int number;
            Add(out number);
            Console.WriteLine("Number after Method Call:{0}",number);
            Console.Read();
        }
    }

Output:
out keyword

Although the ref and out keywords cause different run-time behaviour, they are not considered part of the method signature at compile time. Therefore, methods cannot be overloaded if the only difference is that one method takes a ref argument and the other takes an out argument.