C#: Dispose Unmanaged Resources

facebooktwittergoogle_plusredditpinterestlinkedinmail

When the garbage collector runs it can clean up your managed resources. The garbage collector does not know how to free unmanaged resources (such as file handles, network connections and database connections).

The following are two mechanisms to automate the freeing of unmanaged resources:
Declaring a destructor (or Finalizer) as a member of your class.
Implementing the System.IDisposable interface in your class.
Destructors

Destructors are called before an object is destroyed by the garbage collector.

Example

public class MyClass
{
public static int a;
~MyClass()
{
}
}

When the C# compiler compiles a destructor, it implicitly translates the destructor code to the equivalent of the Finalize() method. That ensures that the Finalize() method of the parent class is executed.

When a C++ object is destroyed, its destructor runs immediately and automatically. However, because of the way the GC works, when using C#, there is no way to know when an object’s destructor will actually execute. Another problem with C# destructors is that the implementation of a destructor delays the final removal of an object from memory. An object that does not have a destructor is removed from memory in one pass of the GC but objects that have destructors require two passes to be destroyed. The first pass calls the destructor without removing the object and the second pass actually deletes the object. If you use destructors frequently and use them to execute lengthy clean-up tasks, the impact on performance can be noticeable.

IDisposable

When a class implements it, normally tells you that the class has unmanaged resources that should be released in a deterministic manner.

unmanagedresources1

Notice that it has only one method, Dispose, and it is within this method’s implementation that the dirty work is done. Thus, you should completely clean up your object and release all resources inside Dispose. Even though the client code, rather than the system, calls Dispose automatically, it’s the client code’s way of saying, “I’m done with this object and don’t intend to use it ever again.”
IDisposable is defined in the system namespace in the Core .NET assembly mscorlib, in other words any class in the base class library or the wider framework or any third-party code can implement IDisposable and you need to know if you are using an instance of a class that disposable, so you can use it properly.

Implementation of IDisposable interface

class Resource : IDisposable  
    {  
        private bool disposed = false;  
        public void Dispose()  
        {  
            Dispose(true);  
            GC.SuppressFinalize(this);  
        }  
 
        private void Dispose(bool disposing)  
        {  
            if (!disposed)  
            {  
                if (disposing)  
                {  
                    // can clean up other managed objects  
                }  
                // clean up unmanaged resources  
                disposed = true;  
            }  
        }  
        ~Resource()  
        {  
            Dispose(false);  
        }  
    }  
    class Program  
    {  
        static void Main()  
        {  
            Resource resource = null;  
            try  
            {  
                resource = new Resource();  
                // use resource  
            }  
            finally  
            {  
                if (resource != null)  
                {  
                    resource.Dispose();  
                }  
            }  
        }  
    }

First notice that Dispose has no parameters and the finalizer call Dispose, has a bool parameter. If called with true, via Dispose without parameters, in other words this object is being called by user code. When called via the finalizer, with false as the parameter, this object is being cleaned up via the GC.

After making sure that this object is cleaned up only once, checking the disposed variable, the Dispose (bool) method checks to see whether it was called by either user code or the GC. The difference is significant because you don’t ever want the GC thread to try cleaning up other managed objects. You see, it is possible that the GC has already cleaned up those objects and you would cause an error, an ObjectDisposedException, by trying to access an object that no longer exists. Regardless of whether this object is being called via user code or the GC, you always need to clean up unmanaged resources, such as OS handles and GDI objects.

Notice that the second statement of Dispose, with no parameters, calls SuppressFinalization. This ensures that the GC won’t try to call the finalizer. That wouldn’t make sense because we just cleaned up the object. It is also more efficient because it helps avoid a second pass of the GC for finalization. The Program class instantiates an object of type DisposableClass. By performing actions in a try/finally block, the program guarantees that the Dispose method will always be called, thus releasing resources immediately when they are no longer needed.

Using Statement

The following code accomplishes the exact same thing as the try/finally block in the preceding code.

using (Resource r = new Resource())
{
// use resource
}

After executing the using statement, the Dispose() method will be called automatically. The parameter to the using statement must be an IDisposable object, otherwise a compile-time error will occur.

Example: Using statement with out IDisposable object

unmanaged3

The following two tabs change content below.

Tom Mohan

Tom Mohan is a technologist who loves to code and build. He enjoys working on Microsoft Technologies. Tom specializes in ASP.NET MVC, Web API , Azure, C# ,WPF, SQL etc and holds a Bachelor engineering degree in Computer Science. Certification : MCSD , MCTS