Thursday, September 14, 2006

A couple of tips about IDisposable (C# .NET)

There are tips that connected to using the disposable pattern and finalization code. Probably it should be included in our code standard document or people should pay attention to it.

Managed types must occasionally encapsulate control over resources that are not managed by the CLR. In such cases, the smallest possible class, or “wrapper”, should be used to encapsulate these resources. Ideally, this thin wrapper should contain just allocation along with provisions for basic access to and freeing of the resources. This small class should provide a destructor (~T()) and implement explicit Dispose method to enable users to free resources owned by an instance deterministically.

Implicit cleanup should always be provided by protecting resources with a SafeHandle. Implementing finalizers by hand is seldom necessary because of this type in the .NET Framework 2.0.

In every case where a type owns resources or it owns types which themselves own resources you should give users the ability to explicitly release them. Developers will then have the oprion to initiate the release of resources once the object is no longer n use. Explicit control should always be provided with a Dispose method based on the IDisposable interface.

Sealed classes that own unmanaged resources without wrappers:

  • Implement a finalizer (~T());
  • Implement IDisposable with a simple method Dispose();

Sealed classes that own wrapped resources:

  • Implement IDisposable with a simple method Dispose();

Not sealed classes that own unmanaged resources without wrappers have to implement complete Disposable pattern (i.e. implement a finalizer ~T(), implement IDisposable interface (Dispose() method, it has to be final (not virtual) method), implement protected virtual void Dispose(bool) method).

Not sealed classes that own wrapped resources don’t have to implement finalizers (just implement IDisposable interface with final Dispose() method) and implement protected virtual void Dispose(bool) method for cleaning the resources.

Do fully implement the dispose pattern on classes with disposable subtypes, even if the base type does not own resources. This will enable programmers coding against the base class to dispose of further derived instances properly.

Do not re-implement IDisposable interface, override void Dispose(), or override Finalize if a base class in your class hierarchy has already defined them according to this pattern. Just override virtual void Dispose(bool) function.

Do not create any other variations of the Dispose methods other than the two specified here: void Dispose() and virtual void Dispose(bool disposing). Dispose should be considered a reserved word in our code standard and used only in context of this pattern to avoid misunderstanding.

Do implement IDisposable pattern on every type that have finalizers (~T()). This gives users of your type a possibility to explicitly clean up resources.

Do allow your Dispose method to be called more than once. It should not generate an exception.

Set to null large managed object fields in your Dispose method.

LandVP LLC

No comments: