Question

J'utilise un modèle d'implémentation IDisposable par défaut (modèle) pour mon code.

extrait:

public void Dispose()
{
    Dispose(true);

    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
        if (isDisposing)
        {
            //cleanup managed resources
        }

        //cleanup unmanaged resources

        this.disposed = true;
    }
}

Ma question: pourquoi l'appel est-il "GC.SuppressFinalize (this)" " dans la méthode publique Dispose? Je placerais " GC.SuppressFinalize (this) " dans le champ "if (isDisposing)" section de la méthode protégée, après avoir disposé des ressources gérées.

Comme ceci:

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
       if (isDisposing)
       {
           //cleanup managed resources

           GC.SuppressFinalize(this);
       }

       //cleanup unmanaged resources

       this.disposed = true;
    }
}
Était-ce utile?

La solution

Je suppose que c'est un cas clair de modèle de conception de modèle.

Votre classe abstraite est conçue pour prendre en charge toutes les tâches importantes / nécessaires requises (ici, GC.SuppressFinalize (this)), et pour permettre à une classe dérivée de ne remplacer qu'une partie du code.

Il y a 2 cas ici:
Snippet 1, SuppressFinalize, in Dispose
Extrait 2, SuppressFinalize, dans Dispose (true)

Ici, l'extrait 1 vérifie que GC.SuppressFinalize est toujours exécuté. Pendant le fragment 2, l’exécution de GC.SuppressFinalize est à la merci de la classe dérivée .

Ainsi, en plaçant GC.SuppressFinalize dans la méthode Dispose, vous en tant que concepteur de votre classe veillerez toujours à ce que, quel que soit le code écrit par les classes dérivées, GC.SuppressFinalize sera exécuté.

C’est uniquement l’avantage d’écrire SuppressFinalize in Dispose plutôt que Dispose (true).

Autres conseils

La méthode Dispose (bool isDisposing) ne fait pas partie de la IDisposable interface.

Vous devriez normalement appeler Dispose (true) à partir de votre Dispose , puis appelez Dispose (false) depuis votre finaliseur, en tant que solution de secours dans le cas où l'objet n'a pas déjà été éliminé.

Appel de SuppressFinalize indique au GC qu'il n'est pas nécessaire d'appeler le finaliseur de votre objet, probablement parce que tout votre nettoyage a été effectué lors de l'appel de Dispose .

Si vous n'avez pas de finaliseur dans votre classe, vous n'avez pas besoin d'appeler SuppressFinalize car il n'y a pas de finaliseur à supprimer!

Joe Duffy a quelques consignes relatives à l'élimination, la finalisation, la collecte des déchets, etc. .

Je pense que l'une ou l'autre disposition aurait pu être choisie, mais ils souhaitaient probablement mettre l'accent sur "mettre tout le code de désallocation dans cette méthode". dans la méthode Dispose protected, ils placent donc l’autre artefact de disposer (Suppression de la finalisation) ailleurs.

De plus, supposons qu'une classe dérivée ait une autre raison d'appeler la méthode Dispose protégée, mais souhaite néanmoins que la finalisation se produise (pour une raison imaginée, je ne le sais pas).

La cause .Dispose se produit lorsque le code géré (votre code) élimine l'objet, désactivant ainsi la finalisation. Les gens créent généralement une autre route vers Dispose (bool élimining) via un finaliseur et l'appel n'aurait aucun sens pour le finaliseur.

L’idée est que votre code de nettoyage ne doit être appelé qu’une fois. Toutefois, il existe deux points d'entrée: la méthode Dispose et les finaliseurs d'objet. Lorsque Dispose est appelé, vous désactivez la finalisation afin que votre code de nettoyage ne soit appelé qu'une fois. Le code ici pourrait mieux illustrer ce code.

Citation:

// NOTE: Leave out the finalizer altogether if this class doesn't 
// own unmanaged resources itself, but leave the other methods
// exactly as they are. 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top