FxCop backlog themes: Disposition and finalization

I skipped ahead a while back with my post on the exceptions theme, and it’s time to get back on track with stuff that would usually precede that rather involved topic during an FxCop backlog cleanup project.


The good news with the disposition and finalization topic is that its scope is quite a bit narrower than the exceptions topic. The bad news is that you’ll probably see almost as many preconceptions regarding how it works, particularly if you have quite a few developers who are accustomed to deterministic finalization. As with the exceptions topic, it’s probably a pretty good idea to start the topic from scratch, making the assumption that most of the developers on your team will get at least something from coverage of even the fundamentals of the subject matter.



Resources


This time around, Chris Brumme’s post on finalization is absolutely required reading, at least for the topic trainer. If you don’t understand at least 90% of that article, you probably don’t know enough about finalization to be teaching the topic.


You’ll also need some resources that are more on the “how to” side of things. The MSDN articles Implementing Finalize and Dispose to Clean Up Unmanaged Resources and Implementing a Dispose Method to provide a reasonable starting point around guidelines for finalization and disposition. By the time you complete your training on finalization and disposition, all the developers on your team should be able to read and understand these articles.



Some gotchas


By and large, the documentation available is pretty clear, and the recommended practices are relatively unambiguous. However, we did run into a few picky detail issues while tackling the disposition and finalization theme at FinRad:


  1. In a disposable class that contains a collection of disposable items, how does one deal with exceptions that might be thrown during the disposition of any individual item?
    The issue here is that one wants to continue disposing of any remaining items even if an exception is thrown while disposing of any given item. However, one still wants to throw an exception out of the parent class Dispose method. The question here is exactly what should one end up throwing? One answer is to store any exceptions into some custom exception that contains an exception collection, then throw the resulting beastie at the end of the process. Unfortunately, there are several problems with this approach, not least of which is that the original Dispose method caller isn’t likely to be want to iterate over the exception collection trying to decide what to do about each and every one of the member exceptions.

    What we ended up deciding to do instead was to treat disposition of each individual collection item as if it we were disposing a field on the parent class. In other words, we wanted to expose the same exception scenario that would be seen if we were able to code the parent Dispose method like this:
    try
    {
    	this._someDisposableField.Dispose();
    }
    finally
    {
    	try
    	{
    		this._someOtherDisposableField.Dispose();
    	}
    	finally
    	{
    		try
    		{
    			this._collectionOfDisposables[0].Dispose();
    		}
    		finally
    		{
    			try
    			{
    				this._collectionOfDisposables[1].Dispose();
    			}
    			finally
    			{
    				…
    			}
    		}
    	}
    }
    If one were able to do this, the only exception the caller of the parent class Dispose method would see is the last exception thrown in any of the individual try blocks. This is quite easy to simulate even while disposing in a loop. e.g.:
    try
    {
    	this._someDisposableField.Dispose();
    }
    finally
    {
    	try
    	{
    		this._someOtherDisposableField.Dispose();
    	}
    	finally
    	{
    		try
    		{
    			Exception lastException = null;
    			foreach (IDisposable item in this._collectionOfDisposables)
    			{
    				try
    				{
    					item.Dispose();
    				}
    				catch (Exception ex)
    				{
    					lastException = ex;
    				}
    			}
    
    			if (lastException != null) throw lastException;
    		}
    		finally
    		{
    			GC.SuppressFinalize(this);
    		}
    	}
    }
    Is this ideal? Obviously not, but I happen to believe that it presents less problems than any of the alternatives. If you think you have a better approach, I’d love to hear about it.
  2. What exactly is an unmanaged resource?
    The basic rules for implementing disposition and finalization are the following:
    • If a class has a disposable field, it should disposed from the Dispose method of the parent class.
    • If a class has a field that represents an unmanaged resource, this should be released from both the Dispose method and the finalizer of the parent class.
    The first rule is pretty unambiguous, but what exactly qualifies as an “unmanaged resource” that should be released both on disposition and finalization of the parent class? Most of the articles on disposition and finalization make some airy-fairy mention of things like database connections and file handles, but does that mean a SqlConnection should be disposed in the parent class finalizer? The simple answer is “no”. The barely more complicated answer is pretty much the only things you should be cleaning up during finalization are IntPtr fields. If you’ve gone beyond IntPtr to start using SafeHandle in .NET 2.0, you don’t even need worry about those since the unmanaged handle is already wrapped in a disposable, finalizable managed object.
  3. There’s no framework design guideline with respect to interface inheritance from IDisposable, but there probably ought to be.
    Interfaces that are likely to be implemented by types that will need to be disposable should themselves be disposable. This is because you don’t want to end up having to write code that looks like this:
    IShouldBeDisposableButIsNot thingy = Factory.CreateThingammy();
    try
    {
    	//…
    }
    finally
    {
    	IDisposable disposableThingy = thingy as IDisposable;
    	if (disposableThingy != null) disposableThingy.Dispose();
    }
    Instead, you want to be able to simply write code like this:
    using (IShouldBeDisposableAndIs thingy = Factory.CreateThingammy())
    {
    	//…
    }


The built-in rules


Here are the built-in rules that you’ll want to start activating during the disposition and finalization theme:


Category Rule In FxCop 1.35? In VStudio 2005?
Design ImplementIDisposableCorrectly x x
TypesThatOwnDisposableFieldsShouldBeDisposable  x x
TypesThatOwnNativeResourcesShouldBeDisposable x
Performance  DisposeMethodsShouldCallSuppressFinalize x x
RemoveEmptyFinalizers x  
Reliability  DisposeObjectsBeforeLosingScope   x
 Usage DisposableFieldsShouldBeDisposed x x
DisposableTypesShouldDeclareFinalizer x x
DisposeMethodsShouldCallBaseClassDispose x x
DoNotDisposeObjectsMultipleTimes x
FinalizersShouldBeProtected  x x
FinalizersShouldCallBaseClassFinalizer x x


Some custom rule ideas


We haven’t created any custom rules yet around finalization and disposition at FinRad, but there are at least a couple that I would like to implement eventually:


  • IDisposable.Dispose should be called from within a finally block (and the only other code in the finally block should be a cast to IDisposable)
  • An interface with at least one disposable implementation should itself be disposable

That last one is bound to be interesting to try to author, but I’ve got loads of time to figure out how to implement it since there are quite a few more important rules to tackle first…

2 thoughts on “FxCop backlog themes: Disposition and finalization”

  1. Thank you for the information. I have another “corner case” for your consideration : do you Dispose instances of MemoryStream ?
    As everyone “knows” it holds no unmanaged resources…

    Cheers,
    –Jonathan

  2. There are actually some pretty good reasons to explicitly dispose everything that is disposable, even if that disposition ultimately does very little. For example, if you’re coding against interfaces or base classes as much as possible, you’ll want to ensure that disposition is triggered all the time in order to cover the cases where it actually will have a significant effect (e.g.: if you happen to working with a FileStream rather than a MemoryStream).

    Even if you’re not coding against interfaces or base classes, there is no guarantee that any given type’s disposition will continue to be quite as trivial in future releases. If you’re not disposing your memory streams now and the next version of the .NET Framework adds some significant resource releasing to MemoryStream.Dispose, you may end up with quite a bit of catch-up coding to do.

    To be honest, I have to wonder why one would want to bother avoiding invoking disposition for the trivial cases. After all, if the Dispose method doesn’t happen to do much of anything, its performance cost will be tiny, so there doesn’t seem to be much point in going out of one’s way to avoid executing it.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>