280 votes

Quand devrais-je utiliser GC.SuppressFinalize()?

En .NET, dans quelles circonstances devrais-je utiliser GC.SuppressFinalize()?

Quel avantage(s) me donne l'utilisation de cette méthode?

291voto

Robert Paulson Points 10792

SuppressFinalize ne doit être appelé que par une classe qui a un finaliseur. Cela informe le Garbage Collector (GC) que this objet a été entièrement nettoyé.

Le modèle IDisposable recommandé lorsque vous avez un finaliseur est :

public class MyClass : IDisposable
{
    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // appelé via myClass.Dispose().
                // OK d'utiliser toutes les références d'objets privés
            }
            // Libérer les ressources non managées.
            // Définir les champs importants à null.
            disposed = true;
        }
    }

    public void Dispose() // Implémentez IDisposable
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~MyClass() // le finaliseur
    {
        Dispose(false);
    }
}

Normalement, le CLR garde un œil sur les objets avec un finaliseur lorsqu'ils sont créés (ce qui les rend plus coûteux à créer). SuppressFinalize indique au GC que l'objet a été nettoyé correctement et n'a pas besoin d'aller dans la file d'attente du finaliseur. Cela ressemble à un destructeur C++, mais n'agit rien du tout de la même façon.

L'optimisation SuppressFinalize n'est pas anodine, car vos objets peuvent vivre longtemps en attendant dans la file d'attente du finaliseur. Ne soyez pas tenté d'appeler SuppressFinalize sur d'autres objets, il s'agit d'un défaut grave en attente de se produire.

Les directives de conception nous indiquent qu'un finaliseur n'est pas nécessaire si votre objet implémente IDisposable, mais si vous avez un finaliseur, vous devez implémenter IDisposable pour permettre un nettoyage déterministe de votre classe.

La plupart du temps, vous devriez pouvoir vous en sortir avec IDisposable pour nettoyer les ressources. Vous ne devriez avoir besoin d'un finaliseur que lorsque votre objet détient des ressources non managées et que vous devez garantir que ces ressources sont nettoyées.

Remarque : Parfois les codeurs ajouteront un finaliseur aux versions de débogage de leurs propres classes IDisposable afin de tester que le code a correctement disposé de leur objet IDisposable.

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

#if DEBUG
~MyClass() // le finaliseur
{
    Dispose(false);
}
#endif

37voto

Michael Burr Points 181287

SupressFinalize indique au système que tout le travail qui aurait été effectué dans le finaliseur a déjà été effectué, de sorte que le finaliseur n'a pas besoin d'être appelé. À partir de la documentation .NET :

Les objets qui implémentent l'interface IDisposable peuvent appeler cette méthode depuis la méthode IDisposable.Dispose pour empêcher le garbage collector d'appeler Object.Finalize sur un objet qui n'en a pas besoin.

En général, la plupart des méthodes Dispose() devraient pouvoir appeler GC.SupressFinalize(), car elles devraient nettoyer tout ce qui serait nettoyé dans le finaliseur.

SupressFinalize est simplement quelque chose qui fournit une optimisation qui permet au système de ne pas se donner la peine de mettre l'objet dans la file d'attente du thread du finaliseur. Un Dispose()/finaliseur correctement écrit devrait fonctionner correctement avec ou sans un appel à GC.SupressFinalize().

6voto

BlackWasp Points 3080

Généralement, lors de la mise en oeuvre du modèle IDisposable lorsque vous n'avez pas besoin de finaliser votre objet. Consultez http://www.blackwasp.co.uk/IDisposable.aspx pour des exemples.

6voto

MaxJ Points 59
Dispose(true);
GC.SuppressFinalize(this);

Si l'objet a un finaliseur, .net place une référence dans la file d'attente de finalisation.

Puisque nous avons appelé Dispose(true), cela efface l'objet, donc nous n'avons pas besoin que la file d'attente de finalisation fasse ce travail.

Donc, l'appel de GC.SuppressFinalize(this) supprime la référence dans la file d'attente de finalisation.

2voto

albertein Points 10821

Cette méthode doit être appelée dans la méthode Dispose des objets qui implémentent l'interface IDisposable, de cette façon le GC ne rappellera pas le finaliseur une autre fois si quelqu'un appelle la méthode Dispose.

Voir: Méthode GC.SuppressFinalize(Object) - Microsoft Docs

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X