Destructor In C#

In C# programming, a destructor is a unique method within a class that is employed to execute cleanup tasks prior to removing an object from memory. Each program can have only a single destructor within a class, identified by a tilde (~) preceding the class name.

Destructors are invoked automatically by the garbage collector (GC) prior to the object being reclaimed. They are primarily employed to free unmanaged resources like file handles, database connections, network sockets, and more.

As the .NET garbage collector autonomously handles memory for managed objects, destructors prove beneficial when the class engages with resources such as files, database connections, and native handles.

Syntax:

It has the following syntax:

Example

class class_name {

    // Destructor

    ~class_name()

    {

        // Cleanup code here

    }

}

In this format;

The

  • class class_name: Defines the name of the class.

The

  • ~class_name: Specifies the destructor for the class.
  • C# Destructor Example

Let's consider a scenario to demonstrate the destructor in C#.

Example

Example

using System;



class C# Tutorial

{

    public C# Tutorial()      // using Constructor

    {

        Console.WriteLine("An instance of C# Tutorial class is created.");

    }

    ~C# Tutorial()     // Destructor

    {

        Console.WriteLine("An instance of C# Tutorial class is destroyed.");

        // Cleanup code

    }

}



class Program

{

    static void Main()

    {

        C# Tutorial hello world = new C# Tutorial();



        // garbage collection to define the destructor call

        hello world = null;

        GC.Collect();

        GC.WaitForPendingFinalizers();

    }

}

Output:

Output

An instance of C# Tutorial class is created.

An instance of C# Tutorial class is destroyed.

Explanation:

In this instance, we are demonstrating a class constructor. Upon instantiation of an object from the C# Tutorial class, the constructor is triggered, displaying a message. Subsequently, by setting the object to null, the Garbage Collector is prompted to execute through the utilization of GC.Collect and GC.WaitForPendingFinalizers methods, triggering the destructor. Following this, the destructor automatically executes to carry out necessary cleanup procedures before the object is eliminated.

Key Characteristics of Destructors

Several main characteristics of the destructor in the C# programming language are as follows:

  • A destructor cannot take parameters and does not return any value.
  • It does not have access modifiers (public, private, etc.).
  • Only one destructor is allowed per class.
  • It cannot be called manually. It is executed automatically by the garbage collector.
  • We can only define destructors in classes, not in structs .
  • We cannot inherit or overload the destructor.
  • C# Destructor Example with File Handling

Let's consider a scenario to demonstrate the destructor in C# with file manipulation.

Example

Example

using System;

using System.IO;



class File_hand

{

    private FileStream file;



    // using Constructor

    public File_hand(string fileName)

    {

        file = new FileStream(fileName, FileMode.OpenOrCreate);

        Console.WriteLine("File opened successfully.");

    }



    // using Destructor

    ~File_hand()

    {

        file.Close();

        Console.WriteLine("File closed successfully.");

    }

}



class C# Tutorial

{

    static void Main(string[] args)

    {

        File_hand f = new File_hand("sample.txt");

        Console.WriteLine("Working with file...");

    }

}

Output:

Output

File opened successfully.

Working with file...

File closed successfully.

Explanation:

In this instance, a class named File_hand has been established, with its constructor initiating file opening upon object creation. The destructor guarantees proper closure of the file once the Garbage Collector eliminates the object. This mechanism promotes safe resource handling by automatically freeing the file handle when it becomes unnecessary.

How Destructors Work with the Garbage Collector in C#?

C# implements a non-deterministic garbage collection mechanism, making it unpredictable when the garbage collector will run or the destructor will be called. The runtime determines the optimal moment to free up memory considering the resources at hand and memory constraints.

When to use a Destructor in C#?

In C# development, a destructor is essential when a class is involved in managing unmanaged resources like database connections, network sockets, file operations, and more. The primary purpose of a destructor is to serve as a cleanup tool to guarantee the proper release of unmanaged resources prior to the object's destruction.

C# destructors can act as a secondary safeguard in cases where the Dispose method is not directly called. Additionally, destructors play a crucial role when managing unmanaged resources, and the IDisposable interface along with the Dispose method is effective for resource cleanup. This becomes particularly advantageous when handling interop scenarios involving interactions with native libraries or APIs.

IDisposable and Dispose Pattern in C#

Let's consider a scenario to demonstrate the IDisposable interface and the Dispose Pattern in the C# programming language.

Example

Example

using System;

using System.IO;



class file_handle : IDisposable

{

    private FileStream file;

    private bool disposed = false;



    public file_handle(string fileName)

    {

        file = new FileStream(fileName, FileMode.OpenOrCreate);

        Console.WriteLine("File Opened");

    }



    // Public Dispose method

    public void Dispose()

    {

        Dispose(true);

        GC.SuppressFinalize(this); 

    }



    // using cleanup logic

    protected virtual void Dispose(bool disposing)

    {

        if (!disposed)

        {

            if (disposing)

            {

                // Dispose managed resources

                file?.Close();

                Console.WriteLine("File Closed");

            }



            // Dispose unmanaged resources



            disposed = true;

        }

    }



    // Destructor

    ~file_handle()

    {

        Dispose(false);

    }

}



class C# Tutorial

{

    static void Main()

    {

        using (file_handle fh = new file_handle("sample.txt"))

        {

            Console.WriteLine("Working with file");

        } // Dispose() is automatically invoked

    }

}

Output:

Output

File Opened

Working with file

File Closed

Explanation:

In this instance, we are examining the file_handle class that initiates file opening within its constructor and guarantees proper resource management via the Dispose method, which is automatically triggered upon completion of the using block. Subsequently, the Dispose(bool disposing) method frees up both managed and unmanaged resources, with the destructor serving as a fallback in case the Dispose method is not explicitly invoked.

Destructor and Finalize Method in C#

In C# programming, both destructors and the Finalize method are primarily employed for resource cleanup purposes, although they exhibit variances in their functionality. A destructor in C# essentially acts as a syntax encapsulation for the Finalize method that is inherent to the .NET runtime. When a destructor is coded in C#, the compiler inherently translates it into an override of the Object.Finalize method. Although it is possible to manually override the Finalize method, opting to define a destructor is considered the more straightforward and secure choice.

Syntax:

It has the following syntax:

Example

protected override void Finalize()

{

    try

    {

        // Cleanup code

    }

    finally

    {

        base.Finalize();

    }

}

C# Destructor and Finalize Method Example

Let's consider a scenario to demonstrate the destructor and finalize method in C#.

Example

Example

using System;



class C# Tutorial

{

    public C# Tutorial()

    {

        Console.WriteLine("The Object is created successfully");

    }



    protected override void Finalize()

    {

        try

        {

            Console.WriteLine("Finalize method called: Explicit cleanup.");

        }

        finally

        {

            base.Finalize();

        }

    }

}



class Program

{

    static void Main()

    {

        C# Tutorial obj = new C# Tutorial();

        obj = null;



        GC.Collect();

        GC.WaitForPendingFinalizers();



        Console.WriteLine("Main method execution finished successfully");

    }

}

Output:

Output

main.cs(10,29): error CS0249: Do not override `object.Finalize()'. Use destructor syntax instead

Explanation:

In this instance, we are examining the C# Tutorial class, and then focusing on a constructor responsible for object creation, whereas the Finalize method is automatically invoked by the garbage collector for resource cleanup prior to object destruction. To guarantee the execution of the Finalize method before the main method concludes, the program enforces garbage collection through the utilization of GC.Collect and GC.WaitForPendingFinalizers methods.

Differences between Constructor and Destructor in C#

There exist multiple distinctions between a constructor and a destructor in C#. A few of these variances include:

Features Constructors Destructors
Purpose It initializes the object upon creation. It performs the cleanup operations before destroying the object.
Invocation It is explicitly invoked during the object creation. It is automatically invoked by the Garbage Collector when the object is destroyed.
Resource Allocation It is utilized for resource allocation. It is often utilized for resource deallocation.
Parametrization It can accept parameters for custom initialization. It doesn't allow any parameters.
Instances Several constructors can be defined with different parameters. A class contains only one destructor and doesn't contain any overloads.

Conclusion

In summary, C# destructors provide a means to perform cleanup actions before an object is removed from memory. They are triggered automatically by the garbage collector when an object is no longer accessible. Destructors are particularly handy in situations involving unmanaged resources or interactions with native code. However, in contemporary C# development, adopting IDisposable and incorporating the Dispose pattern is recommended for enhanced and more reliable resource handling.

C# Destructor FAQs

  1. What is destructor in C#?

In C#, a destructor in an essential method that the Garbage Collector automatically triggers before an object is deleted. Its primary purpose is to free up unmanaged resources.

  1. What triggers the execution of a destructor in C#?

In C#, the Garbage Collector (GC) automatically triggers a destructor at an unspecified time.

  1. Is it possible to manually invoke a destructor in C#?

No, it is not possible to directly call the destructor in C#. The Garbage Collector (GC) is responsible for invoking the destructor.

  1. Is it permissible for a struct to contain a destructor in C#?

No, in C#, it is not possible for structs to include destructors. Structs are categorized as value types, and destructors are exclusively applicable to reference types.

  1. Is it feasible to override a destructor in C#?

No, it is not possible to override a destructor in C#. Each class can define its own destructor.

Input Required

This code uses input(). Please provide values below: