Looking at the IDisposable pattern + Finalizer pattern, there is something I don’t understand:
public class ComplexCleanupBase : IDisposable
{
private bool disposed = false; // to detect redundant calls
public ComplexCleanupBase()
{
// allocate resources
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// dispose-only, i.e. non-finalizable logic
}
// shared cleanup logic
disposed = true;
}
}
~ComplexCleanupBase()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
From my understanding the pattern should be implemented like above.
1) Calling Dispose() fires GC.SuppressFinalize(this), which means that the object should not be put on the finalizer queue as its already properly disposed? That helps to free up the object faster?
2) But what if I am not calling Dispose() on this object at all? In that case the finalizer should kick in, correct? But Dispose(false); does absolutely nothing (only setting disposed = true). Is this intended? It feels like as if something is missing…
Question 1: Yes, if GC.SuppressFinalize is not called the object will be placed on the finalizer queue AND will move up a generation (if not already gen 2), which means that the memory for that object will not be reclaimed until the next pass of GC for the new generation.
Question 2: Your comment
//shared cleanup logicis where the shared cleanup logic will go, this is where things other than settingdisposed = truewould happen.Also, an aside: if your dispose logic should only be called once, consider acquiring a
lock, an uncontested lock is very fast in .Net: