‘Using’ the IDisposable Interface

The IDisposable interface can be used for far more than just clearing up resources. When coupled with the ‘using’ keyword, it enables code to be called on exiting a code block.

In C++, destructors could be used to ensure that a post condition was met when a code block exited. For instance, often we wish to set a variable at the start of a code block and then reset it when exiting. For example:

class CSetBoolean
{
public:
   CSetBoolean(BOOL &rfBoolean, BOOL fValue)
      : m_rfBoolean(rfBoolean), m_fValue(rfBoolean)
   {
      m_rfBoolean = fValue;
   }

   virtual ~CSetBoolean()
   {
      m_rfBoolean = m_fValue;
   }

private:
   BOOL &m_rfBoolean;
   BOOL m_fValue;
};

As an example of use, consider the following:

class CExample
{
public:
   CExample()
   {
      m_fValue = FALSE;
   }

   BOOL Function()
   {
      CSetBoolean setBool(m_fValue, TRUE);

      if (!Function1())
      {
         return FALSE;
      }

      if (!Function2())
      {
         return FALSE;
      }

      if (!Function3())
      {
         return FALSE;
      }

      return TRUE;
   }

private:
   BOOL m_fValue;

   BOOL Function1();
   BOOL Function2();
   BOOL Function3();
}

The boolean is set using the CSetBoolean class, which in turn returns the original value on destruction. In this way, it doesn’t matter where Function() exits—the boolean value is always returned to its original state. This facilitates robust code because we know that the post condition for Function() returning m_fValue back to its original state is always met.

The C# Way

So, as the above design method leads to more robust code, can we do a similar thing in C#?

Initially, you might think not. All objects in .NET are created and destroyed using the garbage collector. The time at which garbage collection takes place is arbitrary (unless you explicitly force it), so we can’t use the destructor (or finalizer) of a C# class to perform the above operation.

For more information about garbage collection see here and here.

However, this is where the IDisposable interface, coupled with the ‘using’ keyword, comes to the fore.

IDisposable

The behaviour of this interface has already been documented in other articles (see above), but here’s a brief description.

The IDisposable interface has one method—Dispose(). This method is not called by the garbage collector on destruction of an object. Its purpose is to provide a single interface in which code can force an instance of a class to mark its resources for garbage collection. Any resources that can be released immediately (for example, native handles or memory) are also to be freed.

For instance, all the GDI objects (System.Drawing.Graphics, System.Drawing.Pen, and so forth) implement IDisposable and in MSDN it’s common for example code to explicitly call the Dispose() method after creating instances of these classes. GDI objects are a limited resource, and so should be released as soon as possible to prevent the system from running out of them. Hence, the inheritance from IDisposable.

The ‘using’ Keyword

Any class instance defined in the parameter list of a ‘using’ keyword has its Dispose() member called on exit of the following code block. For instance:

static void Function(Control control)
{
   Graphics g = control.CreateGraphics();
   Pen pen = new Pen(Color.Black);

   using (g, pen)
   {
      // ....
   }  // g and pen have their Dispose() methods called on exit of
      // the code block.

   // creation of an instance in the using keyword's parameter list
   using (Graphics graphics = control.CreateGraphics())
   {
      // ....
   }  // graphics has its Dispose() method called on exit of the
      // code block.
}

This gives us a method for ensuring that post-conditions of code blocks are always met. If the code is enclosed in a ‘using’ block, we know that any classes that are included in the parameter list will always have their Dispose() method called on exit from that block.

This includes the situation where an exception is thrown inside of the code block. Therefore, by using the above C++ example, we can implement in C# in the following manner.

public unsafe class SetBoolean : IDisposable
{
   bool *m_pfBoolean = null;
   bool m_fValue = false;

   public SetBoolean(bool *pfBoolean, bool fValue)
   {
      m_pfBoolean = pfBoolean;
      m_fValue = *pfBoolean;
      *pfBoolean = fValue;
   }

   public void Dispose()
   {
      *m_pfBoolean = m_fValue;
   }
}

public class Example
{
   private bool m_fValue = false;

   public unsafe bool Function()
   {
      fixed (bool *pfValue = &m_fValue)
      {
         using (SetBoolean setBoolean = new SetBoolean(pfValue,
                true))
         {
            if (!Function1())
            {
               return false;
            }

            if (!Function2())
            {
               return false;
            }

            if (!Function3())
            {
               return false;
            }

            return true;
         }
      }
   }

   private bool Function1()
   {
      // do something
      return true;
   }

   private bool Function2()
   {
      // do something else
      return true;
   }

   private bool Function3()
   {
      // do another thing
      return true;
   }
}

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read