简体   繁体   中英

C# Implementing Dispose - why need check disposing and disposed?

I searched and did not find the exact answer. I'm learning the correct way of Implementing Dispose . I am wondering why need the 2 bools.

  1. Why need disposing ? Only the destructor calls Dispose (false), so why destructor not force release managed resources?
  2. Why need disposed ? If this object is already disposed, how could the Dispose method be called? Could you tell a scenario when the Dispose is called and disposed is true?

The disposing boolean is there to indicate where Dispose was called from. Was it explicitly called via YourObject.Dispose or a using statement, or was it implicitly called from the finalizer thread.

This differentiation is needed because when Dispose is ran from the finalizer thread, there is no guarantee that any managed objects are still alive in object, thus restricting dispose only to to unmanaged resources owned by the type.

The disposed boolean is there to flag that the object has already been disposed. Say, for example, one does dispose the object, but the implementation lacks GC.SuppressFinalize(this) . Even though the object is disposed, it would still run (again) once it's finalizer executes, and attempt to free those unmanaged resources again, where they have already been released.

The example in the documentation you provided explains this nicely:

protected virtual void Dispose(bool disposing)
{
    if (!disposed)
    {
        if (disposing)
        {
            // Free other state (managed objects).
        }

        // Free your own state (unmanaged objects).
        // Set large fields to null.
        disposed = true;
    }
}

For the second question: the Dispose() method should be callable twice without problems (see IDisposable.Dispose() :

If an object's Dispose method is called more than once, the object must ignore all calls after the first one.The object must not throw an exception if its Dispose method is called multiple times.Instance methods other than Dispose can throw an ObjectDisposedException when resources are already disposed.

A common case is when a Stream object is passed to another Stream object that takes "ownership":

using (var ms = new MemoryStream())
{
    using (var sw = new StreamWriter(ms))
    //using (var sw = new StreamWriter(zip, Encoding.UTF8, 4096, true))
    {

    }

    // false: ms has already been disposed
    bool canWrite = ms.CanWrite;
}

The StreamWriter normally takes ownership on the underlying stream (in this case ms ), so that when the Dispose() of the StreamWriter is called so is the Dispose() of the MemoryStream ... But note that even the MemoryStream is in a using block, so its Dispose() will be called again.

There is no problem here, because the Dispose() of the various Stream classes are correctly implemented. If you want to avoid this double Dispose() , nearly all the Stream classes have an overload that tells them if they must take ownership on the underlying Stream (see the commented row... The argument is called leaveOpen , so by setting it to true the StreamWriter won't Dispose() the underlying stream)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM