Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should Dispose() dispose managed resources and finalizer not?

We all know the System.IDisposable pattern. It's been described a zillion time, also here on StackOverflow:

link: Dispose() for cleaning up managed resources?

The Disposable patterns advises that I should only dispose managed resources if my object is being disposed, not during finalize

You can see that this happens because the following code is advised:

protected void Dispose(bool disposing)
{
    if (disposing)
    {
        // Code to dispose the managed resources of the class
    }
    // Code to dispose the un-managed resources of the class
 }

I know that my class should implement System.IDisposable whenever my class has a (private) member that implements System.IDisposable. The Dispose(bool) should call the Dispose() of the private member if the boolean disposing is true.

Why would it be a problem if the Dispose would be called during a finalize? So why would the following Dispose be a problem if it is called during finalize?

protected void Dispose(bool disposing)
{
    if (myDisposableObject != null)
    {
        myDisposableObject.Dispose();
        myDisposableObject = null;
    }
 }
like image 713
Harald Coppoolse Avatar asked Jul 29 '15 14:07

Harald Coppoolse


1 Answers

When an object's finalizer runs, one of the following will be true of almost any IDisposable object it might hold:

  1. It held the only reference to that other object, and that other object's finalizer has already run, so there's no need to do anything with it.

  2. It held the only reference to that other object, and that other object's finalizer is scheduled to run, even though it hasn't yet, and there's no need to do anything with it.

  3. Other objects are still using the IDisposable object, in which case the finalizer must not call Dispose.

  4. The other object's Dispose method cannot be safely run from a finalizer threading context (or, more generally, any threading context other than the one where the object was created), in which case the finalizer must not call Dispose.

Even in the cases where none of the above would apply, code which knows that will probably know a lot about its cleanup requirements beyond the fact that it implements IDisposable, and should often use a more detailed cleanup protocol.

like image 121
supercat Avatar answered Sep 21 '22 14:09

supercat