67 votes

Depuis .NET est un garbage collector pourquoi avons-nous besoin de les finaliseurs/destructeurs/jetez-modèle?

Si je comprends bien la .net runtime toujours nettoyer après moi. Donc, si je créer de nouveaux objets et j'arrête de leur référencement dans mon code, le moteur d'exécution sera de nettoyer ces objets et de libérer la mémoire qu'il occupe.

Depuis c'est le cas, pourquoi, alors, certains objets ont besoin d'avoir un destructeur ou de disposer de la méthode? Ne pas le moteur d'exécution de nettoyer après eux quand ils ne sont pas référencés plus?

93voto

Yona Points 5205

Les finaliseurs sont nécessaires pour garantir la libération de la rareté des ressources dans le système, comme les descripteurs de fichiers, sockets, les objets du noyau, etc. Depuis le finaliseur fonctionne toujours à la fin de l'objets de la vie, c'est l'endroit désigné pour la libération de ces poignées.

L' Dispose modèle est utilisé pour fournir déterministe de la destruction des ressources. Depuis l' .net runtime garbage collector est non-déterministe (ce qui signifie que vous ne pouvez jamais être sûr que lorsque le moteur d'exécution de collecter des objets anciens et d'appeler leur outil de finalisation), une méthode a été nécessaire pour assurer la déterministe libérer des ressources système. Par conséquent, lorsque vous implémentez l' Dispose modèle correctement, vous fournir déterministe de la libération des ressources et dans les cas où le consommateur est négligent et ne pas détruire l'objet, l'outil de finalisation permettra de nettoyer l'objet.

Un exemple simple de pourquoi Dispose est nécessaire peut être un moyen rapide et sale méthode log:

public void Log(string line)
{
    var sw = new StreamWriter(File.Open(
        "LogFile.log", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None));

    sw.WriteLine(line);

    // Since we don't close the stream the FileStream finalizer will do that for 
    // us but we don't know when that will be and until then the file is locked.
}

Dans l'exemple ci-dessus, le fichier restera verrouillé jusqu'à ce que le garbage collector appelle le finaliseur sur l' StreamWriter objet. Cela pose un problème car, dans l'intervalle, la méthode peut être appelée de nouveau à écrire un journal, mais cette fois, ce sera un échec car le fichier est toujours verrouillé.

La manière correcte est de disposer de l'objet lorsque sont effectuées à l'aide:

public void Log(string line)
{
    using (var sw = new StreamWriter(File.Open(
        "LogFile.log", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))) {

        sw.WriteLine(line);
    }

    // Since we use the using block (which conveniently calls Dispose() for us)
    // the file well be closed at this point.
}

BTW, techniquement finaliseurs et destructeurs signifient la même chose; je ne préfère appeler c# destructeurs 'finaliseurs", car sinon, ils ont tendance à embrouiller les gens avec le C++ destructeurs, qui à la différence de C# sont déterministes.

20voto

Konrad Rudolph Points 231505

Les réponses précédentes sont bonnes, mais permettez-moi de souligner le point important, ici, une fois de plus. En particulier, vous avez dit que

Si je comprends bien la .net runtime toujours nettoyer après moi.

Ce n'est que partiellement correcte. En fait, l' .NET seulement offre une gestion automatique pour une ressource particulière: la mémoire principale. Toutes les autres ressources besoin d'un nettoyage manuel.1)

Curieusement, la mémoire principale obtient un statut spécial dans presque toutes les discussions sur les ressources du programme. Il y a bien sûr une bonne raison pour cela – la mémoire principale est souvent la ressource la plus modérée. Mais il est bon de se rappeler qu'il existe d'autres types de ressources, qui doivent aussi gérer.


1) L'habitude de tentative de solution est de coupler la durée de vie d'autres ressources pour la durée de vie de la mémoire de lieux ou les numéros d'identification dans le code – d'où l'existence des finaliseurs.

9voto

Michael Stum Points 72046

Le Garbage Collector ne fonctionnera que si le système n'est pas sous pression de mémoire, sauf si il a vraiment besoin de libérer de la mémoire. Cela signifie, que vous ne pouvez jamais être certain, quand le GC va s'exécuter.

Maintenant, Imaginez que vous êtes une Connexion de Base de données. Si vous laissez le GC nettoyer après vous, vous pouvez être connecté à la base de données pour beaucoup plus longtemps que nécessaire, provoquant l'étrange situation de charge. Dans ce cas, vous souhaitez mettre en place IDisposable, de sorte que l'utilisateur peut appeler dispose() ou utilisez la fonction() pour vraiment faire en sorte que la connexion est fermée dès que possible sans avoir à compter sur GC qui peuvent s'exécuter beaucoup plus tard.

Généralement, IDisposable est mis en œuvre sur toute la classe qui travaille avec des ressources non managées.

4voto

orip Points 28225
  1. Il y a des choses que le garbage collector ne peut pas nettoyer après vous
  2. Même avec des choses qu'elle peut de nettoyage, vous pouvez l'aider à nettoyer plus tôt

2voto

Ricardo Villamil Points 3080

La vraie raison est parce que .net de la collecte des ordures n'est PAS conçu pour collecter des ressources non managées, donc le nettoyage de ces ressources se trouve encore dans les mains du développeur. Aussi, l'objet finaliseurs ne sont pas automatiquement appelée lorsque l'objet est hors de portée. Ils sont appelés par le GC à un certain temps indéterminé. Et quand ils ont, GC ne s'exécute pas immédiatement, il attend pour le prochain tour de l'appeler, en augmentant le temps de nettoyer encore plus, pas une bonne chose lorsque vos objets sont maintenant rares ressources non managées (tels que des fichiers ou des connexions réseau). Entrez le jetable modèle, où le développeur peut manuellement la libération des ressources rares à une époque déterminée (lors de l'appel de yourobject.Dispose() ou à l'aide de (...)). Gardez à l'esprit que vous devez appeler GC.SuppressFinalize(ce); dans votre méthode dispose de dire la GC que l'objet a été manuellement éliminés et ne devrait pas être finalisé. Je vous suggère de jeter un oeil à la Conception du Cadre des lignes Directrices livre de K. Cwalina et B. Abrams. Il explique les Jetables motif très bon.

Bonne Chance!

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