Implementing the IDisposable pattern using CodeRush
The IDisposable Pattern is used to release and close unmanaged resources such as files, streams, and handles as well as references to managed objects that use unmanaged resources, held by an instance of the class. For classes that require a resource cleanup, we recommended following the IDisposable pattern, which provides a standard and unambiguous pattern. The pattern has been designed to ensure reliable, predictable cleanup, and to prevent temporary resource leaks.
There are several options to consider when implementing the IDisposable pattern. Let’s take a look at the following code sample:
The problem with this class is that StreamReader and StreamWriter objects use unmanaged resources. If this class is instantiated, and the later is allowed to simply go out of scope, the objects may not be cleaned up immediately and resources will be locked unnecessarily.
To implement the IDisposable pattern, we should first specify the corresponding interface as one of those that our class implements:
The interface contains only a single Dispose method. This is what the public Dispose() method implementation looks like:
The method calls the second parameterized Dispose() method, passing ‘true’ as an argument to indicate that the method has been called manually. Then, it calls the SuppressFinalize() method of the garbage collector, which prevents the finalizer from executing and limits any associated performance degradation, because finalization increases the cost and duration of your object’s lifetime since each finalizable object must be placed on the finalization queue when it is allocated.
The order of two calls inside the Dispose is important, as it ensures that the GC.SupressFinalize()call is only invoked if the Dispose operation is completed successfully. When Dispose calls Dispose(true), the call may fail while an exception is thrown, but when Finalize is called later, it calls Dispose(false). In reality, these are two different calls can execute different portions of the code, even though Dispose(true) fails, Dispose(false) may not.
The second version of the Dispose(bool disposing) method accepts a Boolean parameter that indicates whether the code has been called manually or automatically. If called manually, all managed and unmanaged resources can be released. If the method was called automatically via the garbage collection process, the managed resources will already have been dealt with, so only the unmanaged resources are cleared.
When implementing the Dispose method, we must ensure that all held resources are freed by propagating the call through the containment hierarchy. To give the base classes a chance to cleanup resources, it is required to invoke the base class’ Dispose(bool disposing) method as the last operation, if one is available. Make sure to pass the same value of ‘disposing’ to the base class’ method.
So, the method implementation for the Logger class looks like this:
Because the Dispose method must be called explicitly, objects that implement IDisposable must also add a finalizer, if a class contains unmanaged resources, to handle the release of those resources when Dispose is not called. The finalizer must utilize the Dispose method with the ‘disposing’ parameter set to ‘false’. The false value indicates that the method was not called manually:
Don’t forget to declare the _Disposed field as follows which indicates the state of the object whether it is disposed or not:
As always, CodeRush provides a couple of code providers that allow you to easily implement the IDisposable pattern without having to remember the entire pattern, using the corresponding Implement IDisposable code provider available on the class name:
you can automatically generate the required code to release all unmanaged resources. Just choose the position where you would like to put the pattern’s code:
and you are done:
If you later create new fields that should be disposed, you can utilize the Dispose Fields code provider:
As a result, the Dispose Fields code provider will add the required disposal code for the specified field as illustrated in the preview hint above.
Using Disposable Objects
Implementing the IDisposable pattern is very important when creating objects that hold disposable resources, but this pattern does not dictate you how to use an instance of the resulting class. Unfortunately, there is no way to force developers to call Dispose explicitly when they are done using it, or to force them to use the proper exception handling mechanism to make sure that the Dispose is called even when an exception is thrown.
So, when you use an object that accesses unmanaged resources, it is a good practice to create the instance with a using statement. The using statement automatically calls the Dispose method on the object when the code that is using it has completed. You can create a using statement by utilizing the Introduce Using Statement code provider. For instance, for this code:
the code provider will produce the following code:
Once a class has been disposed, all of its resources should be considered as unreachable. Attempts to continue using the class may be invalid and should be prevented. If the object has been disposed, we can throw an ObjectDisposedException, providing the object name, to indicate the error. This check should be made in all public members of the class.—– Products: CodeRush Pro Versions: 12.1 and up VS IDEs: 2008 and up Updated: Aug/17/2012 ID: C179