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?
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"
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
}
}