Détruire manuellement les objets c#
je suis assez nouveau à apprendre C# (à partir de Java & C++ background) et j'ai une question à propos de l'élimination manuelle des déchets: est-il même possible de détruire manuellement un objet en C#? Je sais que sur le IDisposable
interface, mais supposons que j'ai affaire à une classe que je n'ai pas écrite et qu'elle ne l'implémente pas? Il n'y aurait pas un .Dispose()
méthode, de sorte que et using { }
et .Finalize
toujours protected
ou private
donc ce n'est pas une option non plus.
(j'essaie juste d'apprendre qu'est-ce que possible en C# dans ce cas. Je suppose que si tout le reste échoue je pourrais!--12 -- > hériter l'hypothétique ImNotDisposable
classe de sorte qu'elle implémenter IDisposable.)
8 réponses
vous ne détruisez pas manuellement les objets .Net. C'est ce qui est gestion de l'environnement est tout au sujet.
en fait, si l'objet est réellement accessible, ce qui signifie que vous avez une référence que vous pouvez utiliser pour dire au GC quel objet vous voulez détruire, la collecte de cet objet sera impossible. Le GC va jamais recueillez tout objet qui est encore accessible.
Ce que vous pouvez faire est d'appeler GC.Collect()
pour forcer une collecte générale. Cependant, cette presque jamais une bonne idée.
au Lieu de cela, il est probablement préférable de simplement semblant que tout objet qui n'utilise pas de ressources non gérées et qui n'est pas accessible par tout autre objet de votre programme est immédiatement détruit. Je sais que cela ne se produit pas, mais à ce point l'objet est juste un bloc de mémoire comme les autres; vous ne pouvez pas le récupérer et il sera éventuellement recueilli, donc il peut tout aussi bien être mort pour vous.
Une dernière remarque sur IDisposable
. Vous ne devez l'utiliser que pour les types qui enveloppent non géré ressources: des choses comme les sockets, les connexions aux bases de données, les objets gdi, etc., et l'abonnement occasionnel événement/délégué.
Si l'objet n'est pas accessible, alors vous pouvez appeler GC.Collect()
et l'objet sera détruit. Le concept de IDisposable
n'a rien à voir avec le CLR et est principalement pour le code utilisateur à implémenter pour effectuer supplémentaire logique d'élimination. Appeler Dispose () sur un objet ne libérera pas l'objet lui-même de la mémoire, bien qu'il puisse très bien disposer de toutes les ressources que cet objet renvoie.
je dois ajouter que bien que ce que j'ai dit soit un moyen d'atteindre cet objectif, en 99.9999% de les applications que vous ne doit jamais appeler GC.Collect()
parce que ça va souvent dégrader les performances de votre application au lieu de l'améliorer.
bien que vous puissiez déclencher la collecte des ordures (vous devez déclencher la génération GC pour toutes les générations parce que vous ne pouvez pas être sûr de la génération dans laquelle se trouve l'objet finalisable), vous ne pouvez pas nécessairement forcer la finalisation d'un objet particulier. Vous ne pouvez compter que sur des suppositions sur le fonctionnement du collecteur d'ordures.
Furtnermore, puisque la finalisation se produit sur son propre fil, vous devriez appeler Waitforpendingfinalisers après le déclenchement des ordures collection.
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
comme d'autres l'ont fait remarquer, cela peut en fait nuire au rendement de votre application parce que le fait d'invoquer inutilement le GC peut promouvoir des objets autrement éphémères dans les générations supérieures, qui sont plus coûteux à recueillir et qui sont recueillis moins fréquemment.
en général, une classe qui implémente un finalizer (destructor) et n'implémente pas IDisposable est mal vue. Et tout ce qui implémente IDisposable devrait appeler ça finalizer logique et se suppression de la finalisation à la collecte des ordures.
Jeff Richter a récemment posté un joli petit truc pour réception d'un avis lorsque le ramassage des ordures a lieu.
un autre grand article sur notions de base sur les collecteurs d'ordures et conseils sur la Performance by Rico Mariani (MSFT)
Non, vous ne pouvez pas détruire un objet spécifique.
il est possible d'invoquer le collecteur d'ordures, qui cherchera des objets à détruire, mais ce n'est presque jamais une bonne idée.
Vous forcer le collecteur d'ordures à courir après la variable que vous voulez détruire va hors de portée, mais vous normalement ne voulez pas le faire, car le collecteur d'ordures est plus efficace si on le laisse faire son propre travail.
Forcer la collecte des ordures peut être fait avec GC.Collecter, mais ne le faites pas. En 10 ans comme développeur.net, je n'en ai jamais eu besoin.
il n'est pas possible de détruire un objet de façon déterministe. Le CLR détermine quand l'objet signalé est récupéré. Cela signifie que, même si vous pouvez signaler un objet pour qu'il soit remis en état et vous assurer que les ressources gérées et non gérées sont prêtes pour l'élimination (en mettant en œuvre le modèle IDisposable), le temps réel de libération de la mémoire dépend du CLR. C'est différent de C++ où vous pouvez réellement supprimer quelque chose et il serait libéré alors.
Heureux codage,
Scott
Vous vous ne pouvez pas détruire manuellement un objet "comme c++ supprimer", tout ce que vous pouvez faire est juste fermer toutes les ressources exclusives que l'objet a acquis et null toutes les références à cet objet, de sorte que le GC peut le collecter, aussi ne pas appeler GC.Collect () par vous-même, le processus GC est coûteux, car il doit suspendre tous les autres fils pour recueillir les objets en toute sécurité de la mémoire, alors faites confiance au GC, et il démarrera au besoin.
dites que vous avez une matrice de classe et que vous avez créé deux objets de matrice aMatrix et bMatrix. Dans C# vous pouvez détruire manuellement (finaliser) un objet comme so:
aMatrix = NULL;
GC.Collecter();
le éboueur remarquera que votre amatrice est nulle et la détruira (finalisera). Que ce soit une bonne idée ou non, c'est une autre histoire.