blog.jj5.net (2003 to 2005)

Close() vs. Dispose() and how to implement an interface

Mon Dec 15 23:38:00 UTC+1100 2003

Categories:

One of my pet peeves about the .NET framework API is the way the implementors have gone about implementing both a Close() and a Dispose() method when implementing the IDisposable interface. The logic is that since the object is 'disposable' it has to implement the IDisposable interface, and thus provide a Dispose() method, however it is believed that in some cases it is 'more natural' to 'close' a resource than 'dispose' of it, thus a Close() method is also implemented.

This gives me the shits because since I don't have the source code I can never be certain that one method is simply an alias for the other, and as a result can never be certain whether I should call Dispose(), Close() or both. A classic example is the SqlConnection object.

I'm willing to concede that Close() is often 'nicer' than Dispose(). I really don't care, but I'm not prepared to argue the point. So lets say that we have an object that needs to be 'closed'. We implement a 'Close()' method. But because this object holds external resources we want to be very clear that the Close() method should be called, thus we provide a Dispose() method that calls Close(). Fine. Alternatively we might have Close() call Dispose(), doesn't really matter, except if it is 'more natural' to Close() the resource, then I think there is a strong case that the implementation is inside the Close() method and the Dispose() method simply calls into Close(). There is another very good reason for this, that I'd like to explain, because I think there are some developers who don't realise how this works.

When you implement an interface in C#, you don't have to provide a public implementation of the interface in your class. You can declare that you implement the interface, and then provide your implementation on the interface. By doing this, you don't mix your interface code with your classes code. As a matter of principle, I try to always specifically implement my interfaces. I have created a sample project that shows the various ways that IDisposable could be implemented when a Close() method is preferred. If you download the sample, you will see that the MyClarity class implements the IDisposable interface, but does not directly contain a Dispose() method. This makes for the most clear class definition, and when I design classes I do it this way -- I don't know why the framework developers insisted on including both methods, but they did and now we are stuck with both a crappy interface and the ensuing confusion.

One great feature of the C# language is the 'using' keyword. C# has language level support for the Dispose() pattern via this keyword. Basically when you create an object in a 'using' block it will be disposed of when the block is exited, including if it is exited as the result of an exception. This allows for nice, tidy, clear code. But when there is both a Close() and Dispose() method, then how can a developer use this construct with confidence?

I'd like to see the public Dispose() method depricated in future revisions of the framework when there is a Close() method that provides the same functionality. Of course there should be continued support for the IDisposable interface, with Dispose() on the interface calling the Close() method by convention.

John.


Copyright © 2003-2005 John Elliot