Monday, October 29, 2018

Specific questions about C# Dispose Pattern



I have a few basic questions about the Dispose Pattern in C#.




In the following code snippet, which seems to be a standard way of implementing the dispose pattern, you’ll notice that managed resources are not handled if disposing is false. How/when are they handled? Does the GC come along and handle the managed resources later? But if that’s the case, what does the GG.SuppressFinalize(this) call do? Can someone give me an example of disposing of managed resources? Unhooking events comes to mind. Anything else? The way the pattern is written, it seems they would get disposed (later) if you did nothing in the “if (disposing)” section. Comments?



protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Dispose managed resources.
}


// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
}
disposed = true;

// If it is available, make the call to the
// base class's Dispose(Boolean) method
base.Dispose(disposing);
}

// implements IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}


Is it true what I read about locks in Dispose(bool) in this thread, How do I implement the dispose pattern in c# when wrapping an Interop COM Object?? It says, “Meta-meta comment - as well as that, it's important that you never acquire locks or use locking during your unmanaged cleanup.” Why is that? Does it apply to unmanaged resources as well?




Finally, does on ever implement a finalizer (~MyClass() in C#) without implementing IDisposable? I believe I read somewhere that finalizers and IDisposable are not necessary (or desirable) if there are no unmanaged resources. However, I do see the use of a finalizer without IDisposable in some examples (see: http://www.codeproject.com/KB/cs/idisposable.aspx as one example)
Thanks,
Dave


Answer



This way of implementing the IDisposable pattern is a fail-safe way: In case a client forgets to call Dispose, the finalizer called by the runtime will call Dispose(false) later (Note that this part is missing in your sample).



In the latter case, i.e. when Dispose is called by the finalizer, managed resources will already have been cleaned up because otherwise the object in question would not have been eligible for garbage collection.




But if that’s the case, what does the GC.SuppressFinalize(this) call do?





Running the finalizer comes with additional costs. Therefore it should be avoided if possible. Calling GC.SuppressFinalize(this) will skip running the finalizer and therefore the object can be garbage collected more efficiently.



In general one should avoid relying on finalizers as there is no guarantee that a finalizer will run. Some of the problems with finalizers are described by Raymond Chen in the following post:




When do I need to use GC.KeepAlive?



No comments:

Post a Comment

plot explanation - Why did Peaches' mom hang on the tree? - Movies & TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...