Posts

Showing posts from January, 2010

Revisiting IDisposable

In my last post , I've introduced a better alternative to the official pattern for implementing the IDisposable interface in .NET: public class BetterDisposableClass : IDisposable { public void Dispose() { CleanUpManagedResources(); CleanUpNativeResources(); GC.SuppressFinalize(this); } protected virtual void CleanUpManagedResources() { // ... } protected virtual void CleanUpNativeResources() { // ... } ~BetterDisposableClass() { CleanUpNativeResources(); } } This pattern is easier to understand because it cleanly separates the responsibilities to implement a disposable class that releases unmanaged (native) and managed resources in different methods. Each method is highly focused on a single identifiable task. This concept can be taken one step further, where different classes are created to deal with each concern. First, each unmanaged resource must be encapsulated in its own class: public class NativeDisposable : IDisposa

A Better IDisposable Pattern

In .NET, objects that implement the IDisposable interface are objects that need special cleanup code to run deterministically when they're not needed anymore. (Another interesting use of this interface is to delimit a scope , but I'll focus on the original cleanup use case in this post.) public interface IDisposable { // cleanup resources void Dispose(); } Most .NET languages have a special syntax to automatically call the method Dispose at the end of a scope where the object is used. In C#, this special syntax is implemented with the using statement: using (var stream = File.OpenRead("interestingFile")) { // do something interesting } The compiler expands this code to: var stream = File.OpenRead("interestingFile"); try { // do something interesting } finally { if (stream != null) { ((IDisposable)stream).Dispose(); } } Sweet sugar indeed. To implement the IDisposable interface in a non-sealed class, there's an of