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.
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.