Question

Dans .NET, dans quelles circonstances dois-je utiliser GC.SuppressFinalize () ?

Quels sont les avantages de cette méthode?

Était-ce utile?

La solution

SuppressFinalize ne doit être appelé que par une classe disposant d'un finaliseur. Il informe le collecteur de déchets que cet objet a été entièrement nettoyé.

Le modèle IDisposable recommandé pour un finaliseur est:

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);
    }
}

Normalement, le CLR garde un œil sur les objets avec un finaliseur lors de leur création (ce qui les rend plus coûteux à créer). SuppressFinalize indique au CPG que l'objet a été nettoyé correctement et qu'il n'est pas nécessaire de le placer dans la file d'attente du finaliseur. Cela ressemble à un destructeur C ++, mais n'agit en rien.

L'optimisation SuppressFinalize n'est pas triviale, car vos objets peuvent attendre longtemps dans la file d'attente du finaliseur. Ne soyez pas tenté d'appeler SuppressFinalize sur d'autres objets que vous. C’est un grave défaut qui attend de se produire.

Les directives de conception nous informent 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 le 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 contient des ressources non gérées et que vous devez vous assurer que ces ressources sont nettoyées.

Remarque: Parfois, les codeurs ajoutent un finaliseur pour déboguer les versions de leurs propres classes IDisposable afin de vérifier que le code a correctement supprimé leur objet IDisposable.

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

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

Autres conseils

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

  

Objets qui implémentent l'IDisposable   l'interface peut appeler cette méthode de   la méthode IDisposable.Dispose à   empêcher le ramasse-miettes de   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 juste quelque chose qui fournit une optimisation qui permet au système de ne pas se préoccuper de regarder l’objet dans le thread du finaliseur. Un finaliseur / Dispose () correctement écrit doit fonctionner correctement avec ou sans appel à GC.SupressFinalize ().

Cette méthode doit être appelée sur la méthode Dispose des objets qui implémentent IDisposable. Ainsi, le GC n'appellera pas le finaliseur une autre fois si quelqu'un appelle la méthode Dispose.

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

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

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

Etant donné que nous avons appelé Dispose (ture), c'est un objet vide, nous n'avons donc pas besoin de la file d'attente de finalisation pour effectuer ce travail.

Appelez donc GC.SuppressFinalize (this) supprime la référence dans la file d'attente de finalisation.

Si une classe, ou quelque chose qui en dérive, peut contenir la dernière référence active à un objet avec un finaliseur, alors GC.SuppressFinalize (this) ou GC.KeepAlive (this ) doit être appelé sur l'objet après toute opération susceptible d'être affectée négativement par ce finaliseur, afin de garantir que le finaliseur ne s'exécutera pas tant que l'opération ne sera pas terminée.

Le coût de GC.KeepAlive () et de GC.SuppressFinalize (this) est essentiellement le même dans toutes les classes ne disposant pas de finaliseur, et les classes qui Les finaliseurs doivent généralement appeler GC.SuppressFinalize (this) , de sorte que cette dernière fonction constitue la dernière étape de Dispose () ne sera peut-être pas toujours nécessaire, mais elle aura été gagnante. ne pas se tromper.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top