destruction en règle d'un objet perso en .NET - C#/.NET managed - Programmation
Marsh Posté le 29-03-2007 à 17:39:22
essaie de lui affecter "null" (ou "nothing" en vb) avant de le supprimer de la collection.
vérifie aussi que tu arrêtes bien tes timers dans ton destructeur.
mais pour faire proprement, tu dois le faire dériver de IDisposable et ajouter une méthode public "Dispose()" qui effectue tout ce travail de nettoyage. (à ce moment, le destructeur fait un appel à Dispose() puis éventuellement détruit quelques petits bouts en plus)
Marsh Posté le 29-03-2007 à 18:35:30
Salut à toi et merci pour pour ton aide.
Lui affecter nothing ne sert n'aura servi à rien, si ce n'est qu'à détruire le pointeur auquel j'ai assigné nothing. L'objet lui, continue son chemin.
En revanche ta seconde proposition me semble très approprié !
Comment faire pour dériver ma class en IDisposable ?
Quand tu dis le destructeur fait un appel à Dispose(), c'est automatique ou c'est à moi d'appeler ma méthode public Dispose ?
Si je comprends bien donc, je dois donc faire le travail de nettoyage moi-même à l'intérieur même de ma classe. Toutefois si j'arrête à la mano les timers, comment saurais-je une fois qu'ils sont arrêtés, que la class est vraiment détruite ?
Quelqu'un peut-il me poster un exemple de ces sub dispose & compagnie ?
Merci beaucoup.
Marsh Posté le 29-03-2007 à 19:09:14
public class maClass : IDisposable
{
object maVariable;
public maClass()
{
maVariable = new ...;
}
public void Dispose()
{
if (maVariable != null)
{
maVariable.Dispose(); // Important pour un timer par exemple, qui pourraît bien s'autoréférencer ailleurs que dans ton objet, notamment parcequ'un timer tourne dans un thread séparé
maVariable = null;
}
}
~maClass()
{
Dispose();
// Eventuellement d'autres ménages
}
}
maClass test = new maClass();
maCollection.Add(test);
maCollection[0].Dispose(); // Normalement, cette ligne est inutile, puisque le destructeur est censé être appelé
maCollection.RemoveAt(0);
Marsh Posté le 29-03-2007 à 19:13:52
MagicBuzz a écrit : essaie de lui affecter "null" (ou "nothing" en vb) avant de le supprimer de la collection. |
ca implémente l'interface IDisposable, ca n'en dérive pas.
Marsh Posté le 29-03-2007 à 19:16:01
ouais, chuis pas trop fluent avec les dénomination
"tu fourres le truc dans le bidule et quand tu machine le bignou ça proutch" <= c'est tellement plus clair
Marsh Posté le 30-03-2007 à 09:25:19
Merci à tous pour vos explications !
Toutefois je me retrouve maintenant avec 2 solutions, mais laquelle choisir ?
Harkonnen m'a pointé vers le fonctionnement de Finalize qui est donc finalement la même chose plus ou moins que Dispose puisque j'y ferais le ménage.
Mais que faire ? Dispose ou Finalize ?
Le mieux niveau nettoyage, vitesse, ressource, c'est quoi ?
Merci encore.
Marsh Posté le 30-03-2007 à 09:29:10
Celiphane a écrit : Merci à tous pour vos explications ! |
fait plus confiance à Harko (chieur ) il a bien plus d'expérience que moi en ce qui concerne .NET
Marsh Posté le 30-03-2007 à 09:50:42
D'après ce lien : http://msdn2.microsoft.com/fr-fr/l [...] S.80).aspx
Je dirais en fait qu'Harko n'apporte pas une solution supplémentaire, mais des précisions.
Effectivement, en .NET il n'y a pas de "destructeur" à proprement parler si je pige bien l'article, mais une méthode surchargeable Finalize().
En C# et C++, on utilise une syntaxe de destructeur, mais en VB.NET et J#, qui n'ont pas de destructeurs, on doit fait un appel explicit à cette méthode.
C'est bien ça Harko ?
Toujours est-il que le "Dispose" est un "nice to have" à rajouter une fois que t'as un destructeur qui fait correctement son travail.
Et l'article qu'a filé Harko confirme ce que j'avais dit au début : effectivement, si on ne dit pas comment fermer un fichier au GC, il ne sait pas le faire tout seul.
Marsh Posté le 30-03-2007 à 09:52:04
Citation : |
Marsh Posté le 30-03-2007 à 10:56:05
Celiphane a écrit : Merci à tous pour vos explications ! |
Les méthodes Finalize sont appelées quand le GC collecte l'objet. Il vaut mieux éviter de créer des types Finalizables, pour les raisons suivantes :
- Tu n'as aucune idée du moment auquel la méthode sera appelée, et donc du moment auquel ton objet sera libéré
- Les objets Finalizables sont plus longs à créer car ils sont placés sur la liste de Finalization du GC
- Les objets Finalizables peuvent être promus dans des générations plus anciennes (en terme de GC), ce qui sollicite davantage la mémoire
- Un objet Finalizable peut avoir une référence sur un autre objet, augmentant ainsi inutilement sa durée de vie
- Le CLR ne te garantit pas l'ordre dans lequel les méthodes Finalize seront appelées pour des objets dépendants. Si par exemple tu as un objet qui contient une référence sur un autre objet, et que le GC détecte que ces 2 objets sont collectables, il est fort possible que l'objet pointé soit libéré avant l'objet qui le pointe, pouvant aboutir à des résultats imprévisibles...
La méthode Finalize est appelée par le GC dans les circonstances suivantes :
- La génération 0 de la mémoire est pleine
- Appel explicit à GC.Collect()
- Le CLR décharge un domaine d'Application
- Le CLR est en cours de fermeture
Si tu veux faire les choses proprement, alors tu dois implémenter le pattern Dispose.
http://haacked.com/archive/2005/11 [...] ttern.aspx
Marsh Posté le 30-03-2007 à 10:59:10
MagicBuzz a écrit : |
Oui, sauf qu'il vaut mieux utiliser le pattern Dispose au lieu d'appeler explicitement Finalize()
MagicBuzz a écrit : |
Si, cf ma réponse au dessus
Marsh Posté le 30-03-2007 à 13:52:00
Harkonnen a écrit : Oui, sauf qu'il vaut mieux utiliser le pattern Dispose au lieu d'appeler explicitement Finalize() |
=> Mouif, mais alors pkoi t'as mis un lien sur Finalize ? (/me n'a rien pigé, comme d'hab )
Harkonnen a écrit : Si, cf ma réponse au dessus |
=> Ouais, m'enfin ce que je voulais dire par "y sait pas faire", c'est qu'il peut aussi bien le détruire 1 ms après la destruction de l'objet appelant, tout comme il peut ne le détruire que 6 heures après.
Marsh Posté le 30-03-2007 à 14:06:48
MagicBuzz a écrit : => Mouif, mais alors pkoi t'as mis un lien sur Finalize ? (/me n'a rien pigé, comme d'hab ) |
me suis chié dessus dans mes favoris, je voulais mettre le lien que je lui ai posté sur Dispose
Marsh Posté le 30-03-2007 à 14:08:35
arf je comprends mieux maintenant
(comment tu m'as trop embrouillé la tête genre dans le topic blabla, regarde-moi ce truc horrible que j'ai fait à cause de toi )
Marsh Posté le 29-03-2007 à 16:32:00
Hello tout le monde,
Voilà j'ai une lacune à combler en VB.NET (ou .net en général).
Dans une appli, j'instancie une class de ma conception (qui contient divers autres objets comme des timers, des sockets etc), elle devient donc un objet et pour le garder en vie une fois sortie de la procédure qui l'a créé, je l'ajoute dans une collection d'objet (qui est public).
Cependant je ne sais pas comment détruire cet objet lorsque je n'en ai plus besoin.
En effet je pensais que le fait de supprimer l'objet de la collection suffirait à détruire le dernier pointeur existant et donc détruirait l'objet, mais une fois ceci fait, je constate via des points d'arrêt que les timers dans mon objet continue de se déclencher, ce qui prouve que l'objet vit toujours quelque part !
Merci de m'éclairer concernant ce concept, et de me dire comment faire afin que je puisse détruire définitivement mes objets.
Cordialement