Search code examples
c#garbage-collectionresharperdisposeidisposable

How can I implement Dispose for IDisposable without the code being recursive?


I'm refactoring some code, unleashing Resharper on it, and came across this:

public virtual void Dispose()
{
    this.Dispose();
}

...which R# flags as potentially problematic with "Function is recursive on all paths"

Which makes sense; however, the "official" (straight from the horse's mouth) code is somewhat similar (Dispose calls Dispose):

public void Dispose()
{
    Dispose(true);
    // This object will be cleaned up by the Dispose method. 
    // Therefore, you should call GC.SupressFinalize to 
    // take this object off the finalization queue 
    // and prevent finalization code for this object 
    // from executing a second time.
    GC.SuppressFinalize(this);
}

...that code wont' even compile, though; I get, "No overload for method 'Dispose' takes '1' arguments"

So how can I both implement Dispose() and not make it recursive?

UPDATE

If I try this (from here):

try
{
    Dispose(true); //true: safe to free managed resources
}
finally
{
    base.Dispose();
}

...I get, "'object' does not contain a definition for 'Dispose'" and "No overload for method 'Dispose' takes '1' arguments"


Solution

  • Looks like you need to implement the Dispose Pattern correctly:

    public class MyThingWithResources : IDisposable
    {
        ~MyTHingWithResources()
        {
            // This is a finalizer and is an optional part.
            // Finalizers are not generally required, and are 
            // intended for clearing up unmanaged resources
            // that your class might hold
    
            // Finalizers are called by the garbage collector
            // So you can never be sure when they are going to
            // be called.
    
            this.Dispose(false);
        }
    
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // if disposing is true, then the method 
                // is being called as part of a managed disposal
                // this means it should be safe to dispose of managed 
                // resources (.Net classes such as System.IO.Stream )
            }
    
            // If disposing is false, the Dispose method was called 
            // from the finaliser, so you're in the last chance saloon 
            // as far as tidying stuff up is concerned.
            // Only unmanaged resources (and the objects that wrap them)
            // should be tidied up in this scenario
        }
    }