Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ObjectDisposedException

Tags:

c#

When implementing the Dispose pattern the object's properties should throw ObjectDisposedException after the object has been disposed.

It seem like a lot of repeated code if every property and method has a line of code at the beginning of the setter and getter to throw that exception even it its just ThrowIfDisposed(). If you have 40 properties that's 80 repeated lines. In a large class it can add up very fast.

I haven't been able to find a better way so it seem like that's just the way it is but I thought I would ask. Is there a better way?

like image 589
JHJ Avatar asked Nov 28 '16 07:11

JHJ


1 Answers

If you have 40 properties in a single class then you probably have a design issue, but moving on... It really depends on the specific use-case, but you should only throw the ObjectDisposedException if the property can't actually be resolved because the class has been disposed. To give a concrete example:

public class MyStream : IDisposable
{
    private string name;
    private Stream stream;

    public MyStream(string name)
    {
        this.Name = name;
        this.Stream = new FileStream(...);
    }

    public string Name
    {
        get
        {
            return this.name;
        }
    }

    public Stream Stream
    {
        get
        {
            if (this.IsDisposed)
            {
                throw new ObjectDisposedException();
            }

            return this.stream;
        }
    }

    private bool IsDisposed { get; set; }

    public void Dispose()
    {
        if (!this.IsDisposed)
        {
            this.IsDisposed = true;
            this.Stream.Dispose();
            this.Stream = null;
        }
    }
}

Here, the property Stream throws an exception because the underlying stream has been disposed, so it can't be used anymore. But Name has no reason to throw. From there, in many cases, you can factorize your code so that access to the actual problematic property throws the exception:

public int Length
{
    get 
    {
        // Since we access the Stream property, the ObjectDisposedException
        // will be thrown when the class is disposed
        return this.Stream.Length;
    }
}

If you still have too many properties to decorate even after following this pattern, you can use libraries like Fody that allows you to inject a behavior at compilation time. Using it, you could make an attribute [ThrowIfDisposed] that you apply on properties as needed.

like image 179
Kevin Gosse Avatar answered Oct 11 '22 22:10

Kevin Gosse