example c# .net garbage-collection idisposable suppressfinalize

c# - example - ¿Cuándo debo usar GC.SuppressFinalize()?



dispose c# example (5)

Ese método debe invocarse en el método Dispose de los objetos que implementan el IDisposable, de esta manera el GC no llamaría al finalizador otra vez si alguien llama el método Dispose.

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

En .NET, ¿en qué circunstancias debo usar GC.SuppressFinalize() ?

¿Qué ventaja (s) me da usar este método?


Si una clase, o algo derivado de ella, puede contener la última referencia en vivo a un objeto con un finalizador, entonces se debe GC.SuppressFinalize(this) a GC.SuppressFinalize(this) o GC.KeepAlive(this) en el objeto después de cualquier operación que pueda ser afectado negativamente por ese finalizador, asegurando así que el finalizador no se ejecutará hasta que se complete esa operación.

El costo de GC.KeepAlive() y GC.SuppressFinalize(this) es esencialmente el mismo en cualquier clase que no tenga un finalizador, y las clases que sí tienen finalizadores generalmente deben llamarse GC.SuppressFinalize(this) , por lo que usar este último La función como último paso de Dispose() puede no ser siempre necesaria, pero no estará mal.


SuppressFinalize solo debe ser invocado por una clase que tenga un finalizador. Es informar al recolector de basura (GC) que this objeto se limpió completamente.

El patrón IDisponible recomendado cuando tienes 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 pestañas en los objetos con un finalizador cuando se crean (lo que los hace más caros de crear). 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 en nada como uno.

La optimización de SuppressFinalize no es trivial, ya que sus objetos pueden vivir mucho tiempo esperando en la cola del finalizador. No tengas la tentación de llamar a SuppressFinalize sobre otros objetos. Ese es un defecto grave esperando a suceder.

Las pautas de diseño nos informan que un finalizador no es necesario si su objeto se implementa como IDisposable, pero si tiene un finalizador, debería implementarlo como IDisposable para permitir la limpieza determinista de su clase.

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

Nota: a veces los programadores agregarán un finalizador para depurar las compilaciones de sus propias clases IDisposibles para probar que el código ha eliminado su objeto IDisposable correctamente.

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 hecho, por lo que no es necesario llamar al finalizador. De los documentos .NET:

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 llame a Object.Finalize en un objeto que no lo requiera.

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

SupressFinalize es solo algo que proporciona una optimización que permite que el sistema no se moleste en poner en cola el objeto al hilo finalizador. Un Dispose () / finalizador escrito correctamente debería funcionar correctamente con o sin una llamada a GC.SupressFinalize ().


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

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

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

Entonces llame a GC.SuppressFinalize (esto) elimine la referencia en la cola de finalización.