#646 – Value Types Don’t Have Finalizers

In .NET, you override the Object.Finalize method to dispose of any unmanaged resources when the object is being garbage collected.  In C#, you write this finalizer using the destructor (~) syntax.  You can also implement the Dispose pattern to allow users of your object to deterministically dispose of  resources.

You cannot implement a finalizer or the dispose pattern for a value type.  A finalizer makes no sense for a value type because value typed objects are not garbage collected–they simply die when they go out of scope.

Since the finalizer and the dispose pattern exist for the purpose of releasing unmanaged resources, and you can’t implement either for a value type, you should avoid using unmanaged resources in value types.  A user would have to explicitly call some method to do the cleanup and there is no guarantee that they would remember to call the method.

Advertisement

#430 – A Dispose Pattern Example

If you want to control when an object’s unmanaged resources are released, you can follow the dispose pattern, implementing a Dispose method.

Here’s a complete example.  We create a method to release resources that is called either when a client invokes Dispose directly or when the CLR is finalizing the object.

    public class Dog : IDisposable
    {
        // Prevent dispose from happening more than once
        private bool disposed = false;

        // IDisposable.Dispose
        public void Dispose()
        {
            // Explicitly dispose of resources
            DoDispose(true);

            // Tell GC not to finalize us--we've already done it manually
            GC.SuppressFinalize(this);
        }

        // Function called via Dispose method or via Finalizer
        protected virtual void DoDispose(bool explicitDispose)
        {
            if (!disposed)
            {
                // Free some resources only when invoking via Dispose
                if (explicitDispose)
                    FreeManagedResources();   // Define this method

                // Free unmanaged resources here--whether via Dispose
                //   or via finalizer
                FreeUnmanagedResources();

                disposed = true;
            }
        }

        // Finalizer
        ~Dog()
        {
            DoDispose(false);
        }
    }

#429 – Use the Dispose Pattern for Deterministic Destruction

You can implement a finalizer in a class to explicitly release unmanaged resources before an object’s memory is freed.  Drawbacks of this approach include:

  • You don’t control when the object’s resources are cleaned up
  • A finalizer can’t make use of any other managed objects  (they may have already been finalized)

Another pattern for releasing unmanaged resources is for a class to implement the IDisposable interface by providing a Dispose method.  Dispose is meant to clean up the object’s resources when it’s called.  A client of the class can decide exactly when it wants to release the object’s resources (deterministic destruction).  Benefits of this pattern include:

  • Can release resources earlier, not waiting for finalization
  • Dispose logic can make use of other managed resources
    public class Dog : IDisposable
    {
        public void Dispose()
        {
            // Release unmanaged resources here

            // Note: need logic to prevent double disposal, etc.
        }