¿Cuándo debería usar GC.SuppressFinalize ()?

En .NET, ¿bajo qué circunstancias debería usar GC.SuppressFinalize() ?

¿Qué ventaja (s) me da el uso de este método?

SuprimirFinalizar solo debe ser llamado por una clase que tenga un finalizador. Está informando al Garbage Collector (GC) que this objeto se limpió por completo.

El patrón IDisposable recomendado cuando tiene un finalizador es:

 public class MyClass : IDisposable { private bool disposed = false; protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // called via myClass.Dispose(). // OK to use any private object references } // Release unmanaged resources. // Set large fields to null. disposed = true; } } public void Dispose() // Implement IDisposable { Dispose(true); GC.SuppressFinalize(this); } ~MyClass() // the finalizer { Dispose(false); } } 

Normalmente, el CLR mantiene las tabs en los objetos con un finalizador cuando se crean (lo que hace que su creación sea más costosa). SuppressFinalize le dice al GC que el objeto se limpió correctamente y no necesita ir a la cola del finalizador. Parece un destructor de C ++, pero no actúa como uno.

La optimización SuprimirFinalizar no es trivial, ya que sus objetos pueden vivir mucho tiempo esperando en la cola del finalizador. No tengas la tentación de invocar SuppressFinalize en otros objetos. Ese es un defecto serio que está por suceder.

Las pautas de diseño nos informan que un finalizador no es necesario si su objeto implementa IDisposable, pero si tiene un finalizador debe implementar IDisposable para permitir la limpieza determinista de su clase.

La mayoría de las veces usted debe poder salir con IDisposable para limpiar los recursos. Solo debe necesitar un finalizador cuando su objeto se atenga a recursos no administrados y debe garantizar que esos recursos se limpien.

Nota: A veces, los codificadores agregarán un finalizador para depurar comstackciones de sus propias clases IDisposables para probar que el código ha eliminado correctamente su objeto IDisposable.

  public void Dispose() // Implement IDisposable { Dispose(true); #if DEBUG GC.SuppressFinalize(this); #endif } #if DEBUG ~MyClass() // the finalizer { Dispose(false); } #endif 

le está diciendo al sistema que cualquier trabajo que se haya hecho en el finalizador ya se ha realizado, por lo que no es necesario llamar al finalizador. De .NET docs:

Los objetos que implementan la interfaz IDisposable pueden llamar a este método desde el método IDisposable.Dispose para evitar que el recolector de basura invoque Object.Finalize en un objeto que no lo requiera.

En general, la mayoría de los métodos Dispose () deberían poder llamar a GC.SupressFinalize (), ya que deberían limpiar todo lo que se eliminaría en el finalizador.

SupressFinalize es simplemente algo que proporciona una optimización que permite que el sistema no se moleste en hacer una búsqueda del objeto con la secuencia del finalizador. Un Dispose () / finalizer correctamente escrito debería funcionar correctamente con o sin una llamada a GC.SupressFinalize ().

Ese método debe invocarse en el método Dispose de objetos que implemente el IDisposable, de esta forma el GC no llamaría al finalizador en otro momento si alguien llama al método Dispose.

Ver: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx

  Dispose(true); GC.SuppressFinalize(this); 

Si el objeto tiene el finalizador, .net pone una referencia en la cola de finalización

Como hemos llamado Dispose (ture), se borra el objeto, por lo que no necesitamos la cola de finalización para realizar este trabajo.

Entonces, llame a GC.SuppressFinalize (this) para eliminar la referencia en la cola de finalización.

Si una clase, o cualquier cosa derivada de ella, puede contener la última referencia en vivo de un objeto con un finalizador, entonces GC.SuppressFinalize(this) o GC.KeepAlive(this) deberían GC.KeepAlive(this) en el objeto después de cualquier operación que pudiera ser adversamente afectado por ese finalizador, asegurando así que el finalizador no se ejecutará hasta después de que se complete la operación.

El costo de GC.KeepAlive() y GC.SuppressFinalize(this) son esencialmente los mismos en cualquier clase que no tenga un finalizador, y las clases que tienen finalizadores generalmente deben llamar a GC.SuppressFinalize(this) , por lo que se usa el último funcionar como el último paso de Dispose() puede no ser siempre necesario, pero no será incorrecto.