WEBINAR:
On-Demand
Application Security Testing: An Integral Part of DevOps
The Dispose MethodExplicit Resource Cleanup
Unlike
Finalize, developers
should call
Dispose explicitly to free unmanaged resources. In fact, you should call the
Dispose method explicitly on
any object that implements it to free any unmanaged resources for which the object may be holding references. The
Dispose method generally doesn't free managed memorytypically, it's used for early reclamation of only the
unmanaged resources to which a class is holding references. In other words, this method can release the unmanaged resources in a deterministic fashion.
However,
Dispose doesn't remove the object itself from memory. The object will be removed when the garbage collector finds it convenient. It should be noted that the developer implementing the
Dispose method must call
GC.SuppressFinalize(this) to prevent the finalizer from running.
Note that an object should implement IDisposable and the
Dispose method not only when it must explicitly free unmanaged resources, but also when it instantiates managed classes which in turn use such unmanaged resources. Implementing IDisposable is a good choice when you want your code, not the GC, to decide when to clean up resources. Further, note that the
Dispose method should not be called concurrently from two or more different threads as it might lead to unpredictable results if other threads still have access to unmanaged resources belonging to the instance.
The IDisposable interface consists of only one
Dispose method with no arguments.
public interface IDisposable
{
void Dispose();
}
The following code illustrates how to implement the
Dispose method on a class that implements the IDisposable interface:
class Test : IDisposable
{
private bool isDisposed = false;
~Test()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
// Code to dispose the managed resources of the class
}
// Code to dispose the un-managed resources of the class
isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
In the preceding code, when the Boolean variable
disposed equals
true, the object can free both managed and unmanaged resources; but if the value equals
false, the call has been initiated from within the finalizer (
~Test) in which case the object should release only the unmanaged resources that the instance has reference to.
The Dispose/Finalize Pattern
Microsoft recommends that you implement both
Dispose and
Finalize when working with unmanaged resources. The correct sequence then would be for a developer to call
Dispose. The
Finalize implementation would run and the resources would still be released when the object is garbage collected even if a developer neglected to call the
Dispose method explicitly. Francesco Balena
writes in his blog "the
Dispose/Finalize pattern should be used only when your type invokes unmanaged code that allocates unmanaged resources (including unmanaged memory) and returns a handle that you must use eventually to release the resource. Both dispose and finalize must chain up to their parent objects by calling their parent's respective methods after they have disposed or finalized their own members".
Simply put, cleanup the unmanaged resources in the
Finalize method and the managed ones in the
Dispose method, when the
Dispose/Finalize pattern has been used in your code.
As an example, consider a class that holds a database connection instance. A developer can call
Dispose on an instance of this class to release the memory resource held by the database connection object. After it is freed, the
Finalize method can be called when the class instance needs to be released from the memory.
According to MSDN, "
Finalize provides a backup to prevent resources from permanently leaking if the programmer fails to call
Dispose". Please refer to the following link: