Pregunta

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

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

¿Fue útil?

Solución

SuppressFinalize solo debe ser llamado por una clase que tenga un finalizador. Informa al recolector de basura (GC) que este objeto se limpió completamente.

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 pestañas en los objetos con un finalizador cuando se crean (haciéndolos más caros de crear). SuppressFinalize le dice al GC que el objeto se limpió correctamente y que no necesita ir a la cola del finalizador. Parece un destructor de C ++, pero no actúa como uno.

La optimización SuppressFinalize no es trivial, ya que sus objetos pueden vivir mucho tiempo esperando en la cola del finalizador. No caigas en la tentación de llamar a SuppressFinalize en 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 implementa IDisposable, pero si tiene un finalizador debe implementar IDisposable para permitir la limpieza determinista de su clase.

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

Nota: A veces los codificadores agregarán un finalizador para depurar compilaciones de sus propias clases IDisposable para probar que el código ha dispuesto 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

Otros consejos

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

  

Objetos que implementan el IDisposable   la interfaz puede llamar a este método desde   el método IDisposable.Dispose para   evitar que el recolector de basura   llamando a Object.Finalize en un   objeto que no lo requiere.

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

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

Ese método debe invocarse en el método Dispose de los objetos que implementan IDisposable, de esta forma el GC no llamaría al finalizador otra vez 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 finalizador, .net coloca una referencia en la cola de finalización

Como tenemos llamada Dispose (ture), borra el objeto, por lo que no necesitamos la cola de finalización para hacer este trabajo.

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

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

El costo de GC.KeepAlive () y GC.SuppressFinalize (this) son esencialmente los mismos en cualquier clase que no tenga un finalizador, y clases que los finalizadores generalmente deben llamar a GC.SuppressFinalize (this) , por lo que usar la última función como último paso de Dispose () puede no ser siempre necesario, pero ganó ' t estar equivocado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top