Saturday, 31 December 2022

C# Program To Implement IDisposable Interface

 IDisposable is an interface defined in the System namespace. It is used to release managed and unmanaged resources. Implementing IDisposable interface compels us to implement 2 methods and 1 boolean variable – 

  1. Public Dispose() : This method will be called by the consumer of the object when resources are to be released. This method will invoke the Dispose(bool disposing) method. We also notify the Garbage collector(GC) about the current object’s resource cleaning so that GC avoids doing it again at the end.
  2. Protected virtual Dispose(bool disposing): This method is the place where all the variables will be set to null. Also the derived class can override this method and release its own resources. The actual resource cleaning code is written in this method.
  3. Bool disposedValue: To ensure the dispose method is called once we use a boolean variable. The resource cleaning must not happen more than once.

The consumer of the object can call the first disposal method explicitly whenever the resources are no longer required. The garbage collector also cleans the object when it is out of scope. However, it is not capable of releasing a few objects such as files, streams, database connections, window handles, etc.

Syntax:

public interface IDisposable;

Disposable Interface Key Points :

  • The class implementing IDisposable interface must implement the dispose method. 
  • A class having unmanaged resources should implement IDisposable interface.
  • The client or consumer of the object can call the disposal method explicitly when the object is no longer required.
  • Whenever a disposal method is called we need to notify the garbage collector about it so that it ignores that object during the cleaning of objects afterward.
  • If a class has a destructor, the only code in there should be an invocation of Dispose(false) to clean any unmanaged resources at the end.
  • The disposal method should be called only once. To ensure that we use a boolean variable.
  •  If a base class is implementing IDisposable interface the derived classes should not implement the interface again.
  • The Derived class can override the dispose(bool disposing) method and release its resources. 

Using Keyword:

While we can call the Dispose method manually or we can use the Using keyword provided by C#. The Using keyword automatically calls the Dispose method when the scope of the variable is over. It plays a crucial role in improving the performance during garbage collection.

Example 1:

// Code Implementation of IDisposable interface in C#
using System;
  
namespace GFG {
/// <summary>
/// A File class which acts
/// as an unmanaged data
/// </summary>
public class File {
    public string Name
    {
        get;
        set;
    }
  
    public File(string name) { this.Name = name; }
}
  
/// <summary>
/// File Handler class which
/// implements IDisposable
/// interface
/// </summary>
public class FileHandler : IDisposable {
    // unmanaged object
    private File fileObject = null;
  
    // managed object
    private static int TotalFiles = 0;
  
    // boolean variable to ensure dispose
    // method executes only once
    private bool disposedValue;
  
    // Constructor
    public FileHandler(string fileName)
    {
        if (fileObject == null) {
            TotalFiles++;
            fileObject = new File(fileName);
        }
    }
  
    // Gets called by the below dispose method
    // resource cleaning happens here
    protected virtual void Dispose(bool disposing)
    {
        // check if already disposed
        if (!disposedValue) {
            if (disposing) {
                // free managed objects here
                TotalFiles = 0;
            }
  
            // free unmanaged objects here
            Console.WriteLine("The {0} has been disposed",
                              fileObject.Name);
            fileObject = null;
  
            // set the bool value to true
            disposedValue = true;
        }
    }
  
    // The consumer object can call
    // the below dispose method
    public void Dispose()
    {
        // Invoke the above virtual
        // dispose(bool disposing) method
        Dispose(disposing : true);
  
        // Notify the garbage collector
        // about the cleaning event
        GC.SuppressFinalize(this);
    }
  
    // Get the details of the file object
    public void GetFileDetails()
    {
        Console.WriteLine(
            "{0} file has been successfully created.",
            fileObject.Name);
    }
  
    // Destructors should have the following
    // invocation in order to dispose
    // unmanaged objects at the end
    ~FileHandler() { Dispose(disposing : false); }
}
  
class Program {
    static void Main(string[] args)
    {
        Console.WriteLine(
            "Explicit calling of dispose method - ");
        Console.WriteLine("");
  
        FileHandler filehandler = new FileHandler("GFG-1");
        filehandler.GetFileDetails();
        // manual calling
        filehandler.Dispose();
  
        Console.WriteLine("");
        Console.WriteLine("");
        Console.WriteLine(
            "Implicit calling using 'Using' keyword - ");
        Console.WriteLine("");
        using(FileHandler fileHandler2
              = new FileHandler("GFG-2"))
        {
            fileHandler2.GetFileDetails();
            // The dispose method is called automatically
            // by the using keyword at the end of scope
        }
    }
}
}

Output: