Pergunta

Na NET, em que circunstâncias eu deveria usar GC.SuppressFinalize()?

Que vantagem (s) faz usando este método dá-me?

Foi útil?

Solução

SuppressFinalize só deve ser chamado por uma classe que tem um finalizador. É informando o coletor de lixo (GC) que objeto this foi limpo totalmente.

O padrão IDisposable recomendado quando você tem um finalizador é:

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, o CLR mantém o controle sobre os objetos com um finalizador quando eles são criados (tornando-os mais caros para criar). SuppressFinalize diz o GC que o objeto foi limpo corretamente e não precisa ir para a fila finalizador. Parece um destrutor C ++, mas não agir nada parecido com um.

A otimização SuppressFinalize não é trivial, como os objetos podem viver um longo tempo de espera na fila finalizador. Não fique tentado a chamar SuppressFinalize em outros objetos você mente. Isso é um defeito grave esperando para acontecer.

Orientações para o projecto nos informam que um finalizador não é necessário se seus implementos objeto IDisposable, mas se você tiver um finalizador você deve implementar IDisposable para permitir a limpeza determinista de sua classe.

Na maioria das vezes você deve ser capaz de fugir com IDisposable para limpar recursos. Você só deve precisar de um finalizador quando seu objeto prende em recursos não gerenciados e você precisa garantir esses recursos são limpos.

Nota: Às vezes codificadores irá adicionar um finalizador para compilações de depuração de suas próprias classes IDisposable para testar esse código dispôs seu objeto IDisposable corretamente.

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

    #if DEBUG
    ~MyClass() // the finalizer
    {
        Dispose(false);
    }
    #endif

Outras dicas

você está dizendo ao sistema que qualquer que seja o trabalho teria sido feito no finalizador já foi feito, de modo que o finalizador não precisa ser chamado. De docs NET:

objetos que implementam o IDisposable interface pode chamar esse método de o método para IDisposable.Dispose evitar que o colector de lixo a partir de chamando Object.Finalize em um objeto que não exigem.

Em geral, a maioria qualquer Dispose () método deve ser capaz de chamar GC.SupressFinalize (), porque deve limpar tudo o que seria cleand-se no finalizador.

SupressFinalize é apenas algo que fornece uma otimização que permite que o sistema se incomode fila o objeto para o segmento finalizador. A Descarte corretamente escrito () / finalizador deve funcionar corretamente com ou sem uma chamada para GC.SupressFinalize ().

Esse método deve ser chamado no método Dispose de objetos que implementa o IDisposable, desta forma, o GC não iria chamar o finalizador outra vez, se alguém chama o método Dispose.

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

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

Se o objeto tem finalizador, .net colocar uma referência na finalização fila

Uma vez que temos chamada Dispose (ture), claro objeto, de modo que não precisamos fila de finalização para fazer este trabalho.

Assim chamar GC.SuppressFinalize (this) de referência Remove na fila de finalização.

Se uma classe, ou qualquer derivado dele, poderia segurar a última referência ao vivo para um objeto com um finalizador, então ou GC.SuppressFinalize(this) ou GC.KeepAlive(this) deve ser chamado no objeto após qualquer operação que pode ser adversamente afetado por essa finalizador, assim garantindo que o finalizador não será executado até depois que a operação estiver concluída.

O custo de GC.KeepAlive() e GC.SuppressFinalize(this) são essencialmente os mesmos em qualquer classe que não tem um finalizador, e as classes que têm finalizadores geralmente deve chamar GC.SuppressFinalize(this), portanto, usando a última função como a última etapa de Dispose() pode não ser sempre necessário, mas não vai estar errado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top