Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it reasonable to check if this object has been disposed and throw ObjectDisposedException?

In a class that implements IDisposable, when is it reasonable to check if the object has been disposed and throw ObjectDisposedException if it has? In all public methods and properties (except Dispose)? Sometimes? Never?

like image 504
Johann Gerell Avatar asked May 27 '11 09:05

Johann Gerell


People also ask

How do you check if an object is disposed or not C#?

Notice the check on _disposed . If you were to call a Dispose method implementing this pattern, you could call Dispose as many times as you wanted without hitting exceptions.

How do you know if dbContext is disposed?

Having the IsDisposed method defined, you can check if the context is disposed before calling SaveChanges (or any other method that are dangerous to be invoked on a disposed context): if ((dbContext != null) && (! dbContext.

What is ObjectDisposedException?

An ObjectDisposedException is thrown when you try to access a member of an object that implements the IDisposable interface or IAsyncDisposable interface, and that object has been disposed.

What happens if Dispose is not called?

Implement a finalizer to free resources when Dispose is not called. By default, the garbage collector automatically calls an object's finalizer before reclaiming its memory. However, if the Dispose method has been called, it is typically unnecessary for the garbage collector to call the disposed object's finalizer.


2 Answers

You should implement that check only in methods that don't work on a disposed object.

For example:
If your class closes the database connections or file handles in Dispose, all methods that need those database connections or file handles need to check if the instance is already exposed.

like image 71
Daniel Hilgarth Avatar answered Oct 21 '22 09:10

Daniel Hilgarth


If an object supports IsDisposed, that method itself should never throw; it would be proper for many other methods to throw if IsDisposed returns true, but the exception should be generated by those methods rather than by IsDisposed. One might have a utility method AssertNotDisposed which would throw if an object is disposed, but such behavior would be expected from a method with that name.

Otherwise, I would suggest that there are many cases where it's useful to have an object hold IDisposable object, and be able to Dispose the inner object while maintaining useful state. For example, an object whose function is to show and maintain a modeless dialog box to get information from a user might usefully keep a copy of the contents of the fields even after the box is closed. Such an object should provide a "Close" method which will Dispose the inner Disposable objects but maintain useful state. While it could also have a Dispose method which would call Close but also set a "NoLongerValid" flag that would cause field properties to throw, I don't think that would really add any value.

I will grant that many cases where an object can hold useful state after it has been disposed are indicative of a class which should perhaps be split. For example, the Font class should perhaps be split into a non-disposable FontInfo class (holding a description of a font, but not a GDI handle) and an IDisposable ReadyFont class (inheriting FontInfo, and encapsulating a GDI font object). Routines that use a font could check whether the object they were given was a FontInfo or a ReadyFont; in the former case, they could create a GDI font, use it, and release it; in the latter case, they could use the ReadyFont's GDI font object and release it. The creator of a ReadyFont would then be responsible for ensuring its cleanup.

As it is, I don't know if the system will try to use the GDI object associated with a control's Font property when rendering the control, but I know that it doesn't squawk if the Font is Disposed (even if it's Disposed before assigning it to the Font property!). Controls are certainly capable of creating new GDI fonts if necessary; I don't know whether they always create a new GDI font or if they only do so if the old one has been disposed. The former behavior would seem to be more performant, but unless coded carefully could cause problems if one thread tried to Dispose a Font while another thread was using it.

like image 22
supercat Avatar answered Oct 21 '22 09:10

supercat