Question

Assuming this as the traditional Dispose pattern (taken from devx but seen on many websites)

class Test : IDisposable
{
  private bool isDisposed = false;

  ~Test()
  {
    Dispose(false);
  }

  protected void Dispose(bool disposing)
  {
    if (disposing)
    {
      // Code to dispose the managed resources of the class
    }

    // Code to dispose the un-managed resources of the class

    isDisposed = true;
  }

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

I don't understand why we call GC.SupressFinalize(this). This requires me to write my own managed resource disposal, including nulling my references? I'm a bit lost, I must admit. Could someone shed some light on this pattern?

Ideally, I would like to only dispose my unmanaged resources and let the GC do the managed collecting by itself.

Actually, I don't even know why we specify a finalizer. In any case, the coder should call dispose himself, now shouldn't he? If that's just a fallback mechanism, I'd remove it.

Was it helpful?

Solution

The IDisposable pattern is used so that the object can clean up its resources deterministically, at the point when the Dispose method is called by the client code.

The finaliser is only there as a fallback in case the client code fails to call Dispose for some reason.

If the client code calls Dispose then the clean-up of resources is performed there-and-then and doesn't need to be done again during finalisation. Calling SuppressFinalize in this situation means that the object no longer incurs the extra GC cost of finalisation.

And, if your own class only uses managed resources then a finaliser is completely unnecessary: The GC will take care of any managed resources, let those resources themselves worry about whether they need a fallback finaliser. You should only consider a finaliser in your own class if it directly handles unmanaged resources.

OTHER TIPS

SuppressFinalize only suppresses any custom finalizer.

It does not alter any other GC behavior.
You never need to explicitly null out references. (Unless you want them to be collected early)

There is no difference between a class without any finalizer and an instance on which you've called SuppressFinalize.

Calling SuppressFinalize prevents an extra call to Dispose(false), and makes the GC somewhat faster. (finalizers are expensive)

Note that classes without unmanaged resources should not have a finalizer. (They should still call SuppressFinalize, unless they're sealed; this allows inherited classes to add unmanaged resources)

The SuppressFinalize call exists in case some derived class decides to add a finalizer. If a normal dispose completes successfully, finalization won't be necessary; even if a derived class decides to add one, the SuppressFinalize call will prevent it from executing and interfering with garbage collection.

To understand why this is important, you should think of finalization not as being part of garbage collection, but rather something that happens before it. When a class registers for finalization (automatic on creation, if it overrides Finalize) it is put into a special list called the Finalization Queue. No object in the Finalization Queue, nor any object referenced directly or indirectly by an object in the queue, can be garbage-collected, but if any object in the finalization queue is found to have no rooted references other than from the queue, the object will be pulled from the queue and the finalizer will run. While the finalizer is being dispatched, the object will not be collectable (since a reference will exist during the dispatch); once the finalizer is complete, there will usually not be any references to the object anymore, so it (and objects referenced thereby) will usually be collectable.

Personally, I think the SuppressFinalize is silly, since I can think of no good reason why a derived class should ever have a finalizer. If a derived class is going to add souse unmanaged resources(*) which the parent class will know nothing about, another class should be created for the purpose of holding those resources; the parent class should hold a reference to that. That way, the parent class itself will not need finalization, and objects which are referenced by the parent class won't be needlessly blocked from garbage collection.

From Msdn : " This method sets a bit in the object header, which the system checks when calling finalizers. The obj parameter is required to be the caller of this method. Objects that implement the IDisposable interface can call this method from the IDisposable.Dispose method to prevent the garbage collector from calling Object.Finalize on an object that does not require it. "

So it prevents an extra call from the GC. If it is called from within the the finalizer method, when object is being finalized, then it wont do anything, as it is already being finalised. Otherwise, the GC is allowed to reclaim memory, without finalisation of the object, thus making things faster.

As noted on MSDN executing the Finalize method is costly. By calling dispose you've already self finalized your class so the finalizer doesn't need to be called. The finalizer is implemented in case the Dispose is never called directly by your code (or whoever 'owns' the instance).

// If the monitor.Dispose method is not called, the example displays the following output:
//       ConsoleMonitor instance....
//       The ConsoleMonitor class constructor.
//       The Write method.
//       The ConsoleMonitor finalizer.
//       The Dispose(False) method.
//       Disposing of unmanaged resources.
//       
// If the monitor.Dispose method is called, the example displays the following output:
//       ConsoleMonitor instance....
//       The ConsoleMonitor class constructor.
//       The Write method.
//       The Dispose method.
//       The Dispose(True) method.
//       Disposing of managed resources.
//       Disposing of unmanaged resources.

From https://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize(v=vs.110).aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top