views:

231

answers:

3

Usually not calling Dispose indicates a possible error or sloppy code and may lead to some hard to find bugs. Ideally I would like to spot if Disposed was not called during unit tests.

One of the methods we used was to put Debug.Assert in the Finalizer

#if DEBUG
~MyClass()
{
    Debug.Assert(false, “MyClass.Dispose() was not called”);
}
#endif

And we found ourselves clicking through assert message boxes but it didn’t work well with continuous integration builds that would ignore the popups.

+3  A: 

If you log this somehow instead of using a Debug.Assert, and used dependency injection to specify your logger implementation, then you could use mock testing to catch this. So, your class may take a logger instance in its constructor, or provide a default one, and then behave like this:

public MyClass : IDisposable
{

IEventLogger _eventLogger;

public MyClass() : this(EventLogger.CreateDefaultInstance())
{
}

public MyClass(IEventLogger eventLogger)
{
    _eventLogger = eventLogger;
}

// IDisposable stuff...

#if DEBUG
~MyClass()
{
    _eventLogger.LogError("MyClass.Dispose() was not called");
}
#endif

}
David M
A: 

It is possible to write an fxCop rule to detect this issue.

Also, making sure that all uses of IDisposable are used inside a using{} block makes this much easier to deal with.

the rule I had checked for either manual calls to Dispose() or use of using{}

Manual calls to dispose are of course more difficult to detect in all situations, since there might be flow control or exceptions that may prevent the call from occurring.

Jason Coyne
A: 

You can use a Mock object framework (like RhinoMocks) to make sure IDisposable.Dispose() is called. If Dispose() were not called the framework will automatically fail the build.

boredgeek