Exception Safety and IDisposable Factories

C# is mostly relieved from the stress of exception safety, thanks to garbage collections. But in some cases it must be handled. A common case is factories creating more than one IDisposable object.

Coming from a C++ background, the notion of exception safety is natural to me. For a C++ developer exception safety is as important as… as… ehhmm… I can’t really find any equivalent in C#. I guess that’s good because exception safety is a pain to deal with. The most common reason to care about exception safety in C++ is memory management and in C# that is a non issue thanks to the garbage collector. For other resources C# offers the using construct and in 95% of the cases it deals with the messy details of ensuring that the resource is disposed even in the event of an exception.

Unfortunately there are those 5% that isn’t handled by the using statement. In this post I’ll use a constructor that allocates a precious resource in the form of objects implementing IDisposable. The principle is the same however for any function that creates a IDisposable object whose lifetime will exceed the function execution.

The Problem

Let’s get to some code. This is a simple class holding a precious resource. To make sure that the precious resource is disposed as soon as it is no longer used, the class implements IDisposable (not using the proper full pattern now, to keep the code shorter).

public class NotExceptionSafe : IDisposable
{
    private readonly PreciousResource resource;
 
    public NotExceptionSafe()
    {
        resource = new PreciousResource();
        resource.Open();
    }
 
    public void Dispose()
    {
        resource.Dispose();
    }
}

PreciousResource writes debug output in both the constructor and the Dispose method so we can see that it is properly disposed of. Let’s run the code and test it and see how the resource is allocated and released.

Allocated precious resource.
Caught InvalidOperationException exception (Failed opening!)

Ooopss… it’s only allocated. Then the test runner catches an exception from the Open method.

The problem is that since the NotExceptionSafe instance is never fully constructed it won’t be disposed by the using block (because no object will ever be fully constructed and returned to the using). If the constructor fails, then we’re on our own to handle it.

Using and Disposing of WCF Clients

Designing an interface always requires careful considerations of how it will be used. Scott Meyers elegantly catches the entire problem in one sentence in his book Effective C++:

Make interfaces easy to use correctly and hard to use incorrectly.

The people at Microsoft who were in charge for the WCF client code generation either hadn’t read that book or didn’t understand it. They have made an interface that is counter intuitive and hard to use when it comes to disposing of the WCF client.

In my previous post IDisposable and using in C# I wrote that “Always call Dispose on objects implementing IDisposable“. This is true, as long as the class implements IDisposable in a reasonable way. Unfortunately the WCF client doesn’t. The MSDN docs presents the problem.

using (CalculatorClient client = new CalculatorClient())
{
    ...
} // <-- this line might throw
Console.WriteLine(
  "Hope this code wasn't important, because it might not happen.");

That is definitely an example of an interface that is hard to use. The hidden call to Dispose might throw with a strange exception which sometimes even hides the real error. There is a simple solution though that makes the above code work as expected.

Disposable Base Class

I have covered the IDisposable interface in my previous posts IDisposable and using in C# and Implementing IDisposable. To make the implementation of IDisposable easier, I have written an abstract base class that handles the details of the IDisposable pattern. The objectives of the class is to:

  • Provide a simple, reusable implementation of the disposable pattern.
  • Pass all code analysis rules.

Implementing IDisposable

In the IDisposable and using in C# post I showed how to handle an object that implements IDisposable. That’s the most common scenario, where a simple using will ensure that resources are properly and early released, but that only handles the case when the resource is created and disposed of in the same function. What if the resource is a member of a class?

I have created a simple logging class that writes an opening line whenever the log is opened.

public class LogWriter
{
    private StreamWriter m_Stream;
 
    public LogWriter(string logFile)
    {
        m_Stream = new StreamWriter(logFile, true);
        m_Stream.WriteLine("Starting logging at {0}", DateTime.Now);
    }
 
    public void WriteLine(string message)
    {
        m_Stream.WriteLine(message);
    }
}

The StreamWriter created in the constructor implements IDisposable so we should call it’s Dispose method. But from where? The answer is to let the LogWriter implement IDisposable

IDisposable and using in C#

C# and the .NET environment have automatic memory management through garbage collection. Coming from C++ I think it’s great to not having to worry about memory deallocation. Unfortunately memory from the managed heap (which is where C# objects are placed)  is just one kind of resource in a system. There are several other types of resources:

  • File handles
  • Network sockets
  • Database connections
  • Unmanaged memory

These resources still need to be freed in C#. If the .NET class handling the resource is implemented correctly it will release the unmanaged resource when the object is garbage collected. This is fine as long as it doesn’t matter when the resource is freed. In a program with small memory footprint the garbage collector might never run during the execution of the program, because the low memory usage never triggers a run. In the meantime your program can hold on to an expensive database connection instead of releasing it back to the connection pool for reuse. Eventually the database connection pool is empty and your program (or web site) will start failing.

Software Development is a Job – Coding is a Passion

I'm Anders Abel, a systems architect and developer working for Kentor in Stockholm, Sweden.

profile for Anders Abel at Stack Overflow, Q&A for professional and enthusiast programmers

The complete code for all posts is available on GitHub.

Popular Posts

Archives

Series

Powered by WordPress with the Passion for Coding theme.