Back To Basics - Dispose Vs Finalize

Introduction

We have been using the Dispose method for disposing of objects. NET. For the same purpose, we may also use the Finalize method. In this article, I will try to explain what the Dispose and the Finalize methods are where to use the Finalize, and where to use the Dispose. I will also try to explain the difference between them.

Dispose

The garbage collector (GC) plays the main and important role in .NET for memory management so the programmer can focus on the application functionality. The garbage collector is responsible for releasing the memory (objects) that are not being used by the application. But GC has the limitation that, it can reclaim or release only memory that is used by managed resources. There are a couple of resources that GC is not able to release as it doesn't have information, on how to claim memory from those resources like File handlers, window handlers, network sockets, database connections, etc. If your application has these resources then it's the program's responsibility to release unmanaged resources. For example, if we open a file in our program and not close it after processing then that file will not be available for other operations or if it is being used by other applications they can not open or modify that file. For this purpose, the FileStream class provides the Dispose method. We must call this method after file processing is finished. Otherwise, it will be through exception Access Denied or the file is being used by another program.

Close Vs Dispose

Some objects expose Close and Dispose two methods. For Stream classes, both serve the same purpose. Dispose method calls the Close method inside.

void Dispose()
{
    this.Close();
}

Here question arises, why do we need the Dispose method in Stream? Having the Dispose method will enable you to write the below code and implicitly call the dispose method and ultimately call the Close method.

using(FileStream file = new FileStream("path", FileMode.Open, FileAccess.Read))
{
    // Do something with file
}

But for some classes, both methods behave slightly differently. For example Connection class. If the Close method is called then it will disconnect with the database and release all resources being used by the connection object and the Open method will reconnect it again with the database without reinitializing the connection object. However, the method completely releases the connection object and cannot be reopened just by calling the Open method. We will have to re-initialize the Connection object.

Creating Dispose

To implement the Dispose method for your custom class, you need to implement an IDisposable interface. IDisposable interface exposes the Dispose method where code to release unmanaged resources will be written.

Finalize

Finalize method also called destructor to the class. Finalize method can not be called explicitly in the code. Only the Garbage collector can call the the Finalize when object becomes inaccessible. The finalized method cannot be implemented directly it can only be implemented via declaring a destructor. The following class illustrates, how to declare a destructor. It is recommended that implement the Finalize and Dispose methods together if you need to implement the Finalize method. After compilation destructor becomes the finalized method.

public class MyClass : IDisposable 
{   
    // Constructor    
    public MyClass() 
    {   
        // Initialization   
    }   

    // Destructor also called Finalize    
    ~MyClass() 
    {   
        this.Dispose();   
    }   

    public void Dispose() 
    {   
        // Write code to release unmanaged resource   
    }   
}

Using Finalize

Now the question is When to implement Finalize? There may be any unmanaged resource for example file stream declared at class level. We may not know what stage or which step should be appropriate to close the file. This object is being used in many places in the application. So in this scenario Finalize can be an appropriate location where unmanaged resources can be released. It means, cleaning the memory acquired by the unmanaged resource as soon as the object is inaccessible to the application.

Finalize is a bit expensive to use. It doesn't clean the memory immediately. When the application runs, the Garbage collector maintains a separate queue/array when it adds all objects that have been finalized and implemented. In other term, GC knows which object has Finalize implemented. When the object is ready to claim memory, the Garbage Collector calls the finalize method for that object and removes it from the collection. In this process, it just cleans the memory that is used by unmanaged resources. Memory used by managed resources is still in the heap as an inaccessible reference. That memory is released, whenever Garbage Collector runs next time. Due to the finalized method, GC will not clear the entire memory associated with an object in the first attempt.

Conclusion

It is always recommended that one should not implement the Finalize method until it is extremely necessary. Priority should always be to implement the Dispose method and clean unmanaged as soon as possible when processing finishes.