Table of Contents

Resolving CA2000: Dispose objects before losing scope

What's the problem?

If you're using Code Analysis to ensure that your code satisfies Microsoft's Framework Design Guidelines, sometimes you may encounter CA2000: Dispose objects before losing scope. There are a number of ways it can occur, but there's one particular cause of this warning that can be resolved by a method in Existential.Net, reducing the amount of code you have to write to do so.

The scenario that Existential.Net can help with is when an object that implements the IDisposable interface has to be returned from the method where it's created. The correct way of doing that is to construct the object using a temporary variable inside a try/finally block before assigning it to the variable that will actually be returned. It's not a very intuitive solution, and takes several lines of code - or you can call an Existential.Net method to do it for you.

How do I resolve it?

The type you want to return must implement IDisposable, and have a default constructor. If it meets those conditions, you can call the method Disposable.SafelyReturn<T>(Action<T>); for example:

public MemoryStream GetMemoryStream()
    return Disposable.SafelyReturn<MemoryStream>();

The simplest method is to leave the Action<T> parameter unspecified, in which case it will default to null and the default constructor of T will be used.

If further initialisation of the object's needed, an Action that performs the initialisation can be provided, for example:

public MemoryStream GetMemoryStream()
    long theLengthInBytes = 256;
    return Disposable.SafelyReturn<MemoryStream>(stream => stream.SetLength(theLengthInBytes));

Additional Dispose methods

The Dispose class includes a couple of extension methods for IEnumerable that help to access its members safely. The concrete implementation of the IEnumerator may or may not be disposable; if it is disposable then it should be disposed after use.

The methods Disposable.UsingNonGenericEnumerator(this IEnumerable, Action<IEnumerator>) and Disposable.UsingNonGenericEnumerator<TResult>(this IEnumerable, Func<IEnumerator, TResult>) encapsulate the use of the enumerator so that its lifetime is handled by the method and if it is disposable, it will be disposed correctly. The provided Action or Function will act upon the IEnumerator created by the method call, then if necessary it will be disposed.

As extension methods, these can be called as static members of the Dispose class, but are more likely to be called directly upon an IEnumerable collection as if they were an instance method.