web-dev-qa-db-fra.com

En C #, quelle est la différence entre un destructeur et une méthode Finalize dans une classe?

Quelle est la différence, s'il y en a une, entre un destructeur et une méthode Finalize dans une classe?

J'ai récemment découvert que Visual Studio 2008 considère un destructeur synonyme d'une méthode Finalize, ce qui signifie que Visual Studio ne vous permettra pas de définir simultanément les deux méthodes dans une classe.

Par exemple, le fragment de code suivant:

class TestFinalize
{
    ~TestFinalize()
    {
        Finalize();
    }

    public bool Finalize()
    {
        return true;
    }
}

Donne l'erreur suivante lors de l'appel à Finalize dans le destructeur:

L'appel est ambigu entre les méthodes ou propriétés suivantes: 'TestFinalize. ~ TestFinalize ()' et 'TestFinalize.Finalize ()'

Et si l'appel à Finalize est commenté, il donne l'erreur suivante:

Le type 'ManagementConcepts.Service.TestFinalize' définit déjà un membre appelé 'Finalize' avec les mêmes types de paramètres

88
Jeff Leonard

Un destructeur en C # remplace la méthode System.Object.Finalize. Vous devez utiliser la syntaxe destructrice pour ce faire. Remplacer manuellement Finalize vous donnera un message d'erreur.

Fondamentalement, ce que vous essayez de faire avec votre déclaration de méthode Finalize est cachant la méthode de la classe de base . Cela entraînera le compilateur à émettre un avertissement qui peut être désactivé en utilisant le modificateur new (si cela devait fonctionner). La chose importante à noter ici est que vous ne pouvez pas à la fois override et déclarer un membre new avec un nom identique en même temps, donc avoir à la fois un destructeur et une méthode Finalize entraînera une erreur (mais vous pouvez , bien que ce ne soit pas recommandé, déclarez une méthode public new void Finalize() si vous ne déclarez pas un destructeur).

62
Mehrdad Afshari

Wikipedia a une bonne discussion sur la différence entre un finaliseur et un destructeur dans l'article finalizer .

C # n'a vraiment pas de "vrai" destructeur. La syntaxe ressemble à un destructeur C++, mais c'est vraiment un finaliseur. Vous l'avez écrit correctement dans la première partie de votre exemple:

~ClassName() { }

Ce qui précède est du sucre syntaxique pour une fonction Finalize. Il garantit que les finaliseurs de la base sont garantis pour fonctionner, mais est par ailleurs identique à remplacer la fonction Finalize. Cela signifie que lorsque vous écrivez la syntaxe du destructeur, vous écrivez vraiment le finaliseur.

selon Microsoft , le finaliseur fait référence à la fonction que le garbage collector appelle lorsqu'il recueille (Finalize), tandis que le destructeur est votre morceau de code qui s'exécute en conséquence (la syntaxe sucre qui devient Finalize). Ils sont si près d'être la même chose que Microsoft n'aurait jamais dû faire la distinction.

L'utilisation par Microsoft du terme "destructeur" du C++ est trompeuse, car en C++ il est exécuté sur le même thread dès que l'objet est supprimé ou sauté de la pile, tandis qu'en C # il est exécuté sur un thread séparé à un autre moment.

65
Kenzi

Trouvé ici: http://sanjaysainitech.blogspot.com/2007/06/difference-between-destructor-dispose.html

  1. Destructeur

    Ce sont des méthodes spéciales qui contiennent du code de nettoyage pour l'objet. Vous ne pouvez pas les appeler explicitement dans votre code car ils sont appelés implicitement par GC. En C #, ils ont le même nom que le nom de classe précédé du ~ signe. Comme-

    Class MyClass
    {
    
    ~MyClass()
    {
    .....
    }
    }
    

    Dans VB.NET, les destructeurs sont implémentés en remplaçant la méthode Finalize de la classe System.Object.

  2. Disposer

    Celles-ci sont comme toutes les autres méthodes de la classe et peuvent être appelées explicitement mais elles ont un but spécial de nettoyer l'objet. Dans la méthode dispose, nous écrivons du code de nettoyage pour l'objet. Il est important que nous libérions toutes les ressources non gérées dans la méthode dispose comme la connexion à la base de données, les fichiers, etc. La méthode implémentant la classe dispose doit implémenter l'interface IDisposable. La classe possède un détracteur car elle a déjà effectué le travail de nettoyage de l'objet, il n'est donc pas nécessaire que le garbage collector appelle la méthode Finalize de l'objet. Référence: http://msdn2.Microsoft.com/en-us/library/aa720161 (VS.71) .aspx

  3. Finaliser

    Une méthode Finalize agit comme une sauvegarde pour nettoyer les ressources dans le cas où votre méthode Dispose n'est pas appelée. Vous devez uniquement implémenter une méthode Finalize pour nettoyer les ressources non gérées. Vous ne devez pas implémenter une méthode Finalize pour les objets gérés, car le garbage collector nettoie automatiquement les ressources gérées. La méthode Finalize est appelée implicitement par le GC, vous ne pouvez donc pas l'appeler à partir de votre code.

    Remarque: En C #, la méthode Finalize ne peut pas être remplacée, vous devez donc utiliser un destructeur dont l'implémentation interne remplacera la méthode Finalize dans MSIL. VB.NET, la méthode Finalize peut être remplacée car elle prend en charge la méthode destructrice.

Mise à jour: Discussion semi-connexe intéressante ici .

19
Andrew Siemer