This documentation is archived and is not being maintained.

Implementing a Dispose Method

The pattern for disposing an object, referred to as a dispose pattern, imposes order on the lifetime of an object. The dispose pattern is used only for objects that access unmanaged resources. This is because the garbage collector is very efficient at reclaiming unused managed objects.

A type's Disposemethod should release all the resources that it owns. It should also release all resources owned by its base types by calling its parent type's Dispose method. The parent type's Dispose method should release all resources that it owns and in turn call its parent type's Dispose method, propagating this pattern through the hierarchy of base types. To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.

There is no performance benefit in implementing the Dispose method on types that use only managed resources (such as arrays) because they are automatically reclaimed by the garbage collector. Use the Dispose method primarily on managed objects that use native resources and on COM objects that are exposed to the .NET Framework. Managed objects that use native resources (such as the FileStream class) implement the IDisposable interface.

Important noteImportant

C++ programmers should not use this topic. Instead, see Destructors and Finalizers in Visual C++. In the .NET Framework version 2.0, the C++ compiler provides support for implementing deterministic disposal of resources and does not allow direct implementation of the Dispose method.

A Dispose method should call the SuppressFinalize method for the object it is disposing. If the object is currently on the finalization queue, SuppressFinalize prevents its Finalize method from being called. Remember that executing a Finalize method is costly to performance. If your Dispose method has already done the work to clean up the object, then it is not necessary for the garbage collector to call the object's Finalize method.

The code example provided for the GC::KeepAlive method shows how aggressive garbage collection can cause a finalizer to run while a member of the reclaimed object is still executing. It is a good idea to call the KeepAlive method at the end of a lengthy Dispose method.

Writing code for an object's finalizer is a complex task that can cause problems if not done correctly. Therefore, we recommend that you construct SafeHandle objects instead of implementing the dispose pattern.

The SafeHandle class simplifies object lifetime issues by assigning and releasing handles without interruption. It contains a critical finalizer that is guaranteed to run while an application domain is unloading. For more information about the advantages of using a safe handle, see Safe Handles and Critical Finalization.

The SafeHandle class in the System.Runtime.InteropServices namespace is an abstract wrapper class for operating system handles. Deriving from this class is difficult. Instead, use the derived classes in the Microsoft.Win32.SafeHandles namespace that provide safe handles for the following:

  • Files and pipes.

  • Memory views.

  • Cryptography constructs.

  • Registry keys.

  • Wait handles.

The following code example shows the recommended design pattern for implementing a Dispose method for classes that encapsulate unmanaged resources.

Resource classes are typically derived from complex native classes or APIs and must be customized accordingly. Use this code pattern as a starting point for creating a resource class and provide the necessary customization based on the resources you are encapsulating.

No code example is currently available or this language may not be supported.
Show: