[VB.NET] Dispose

Yop !

Voilà ma petite question. J’ai un bout de code, comme suit :

MonObjet.Dispose() MonObjet = Nothing
Un collègue ayant remarqué cela, m’indique que c’est débile, totalement inutile.
Or je doute. La méthode Dispose est utilisé pour liberer toutes les ressources liées à l’objet.
Mais.

Mais l’objet pointe toujours sur une référence, n’est-il pas ?
Si dans mon code j’ai un test If MonObjet Is Nothing le Dispose suffit-il ?

attention GC.collect est a utilisé avec beaucoup de precaution.

pour l’avoir experimenté, c’a m’a planté le serveur plus d’une fois…

Houla alors on resume:

.Dispose sur un object IDisposable : indispensable, pas une option, mandatory, obligatoire, si tu le fais pas je te tape.

Un finalizer : si t’as un objet IDisposable en general pour faire les choses bien (fxcop t’oblige d’ailleurs) il faut faire un finalizer qui appelle un protected virtual Dispose(false) , alors que le Dispose() appelle le meme protected virtual Dispose(true), pour faire la diff justement parceque le finilazer ne tourne pas sur le meme thread que le reste, dans ce cas appeller SuppressFinalize oeuf corse.

monObjet = null apres qu’on en ait plus besoin… mouai completement optionel pour une variable locale juste inscope a cet endroit, peut etre utile dans des super marginaux et exceptionels dans des grosses fonctions pour encourager la GC a agir plus tot qu’a la fin du scope de la variable. Bien sur si c’est pas une variable locale et que tu sais que c’est la derniere reference a l’objet, il faut, sinon il sera jamais collecte car qqn aura toujours une reference dessus. C’est comme ca qu’on fait des fuites, meme en managed code. En gros si tu sais pas exactement pourquoi tu en as besoin, completement inutile pour les variables locales.

GC.Collect. Evil, a ne pas appeller, sauf si on sait vraiment pile poil exactement ce qu’on est en train de faire. Se fait ultra rarement par appli et uniquement a des moments de changements majeurs de profil de fonctionnements.

Enfin comme pour tout y a des “regles” et des cas ou il est logique de contourner les regles, mais faut surtout comprendre pourquoi.

J’ai du mal m’exprimer. Ou alors je ne sais pas comprendre.

Ce que je voulais dire, c’est que mon collègue m’affirme que mon MonObjet = Nothing ne sert strictement à rien. à cause du Dispose.
Or après avoir discuté avec lui, c’est qu’il sous-entend que le Dispose déréférence l’objet, et donc comme de par magie de .NET, le test If MonObjet Is Nothing est à true.

[quote=« Xas, post:4, topic: 27561 »]J’ai du mal m’exprimer. Ou alors je ne sais pas comprendre.

Ce que je voulais dire, c’est que mon collègue m’affirme que mon MonObjet = Nothing ne sert strictement à rien. à cause du Dispose.
Or après avoir discuté avec lui, c’est qu’il sous-entend que le Dispose déréférence l’objet, et donc comme de par magie de .NET, le test If MonObjet Is Nothing est à true.[/quote]

D’après ce que dis GloP de toute façon tu ne dois utiliser ni l’un ni l’autre. :stuck_out_tongue:

Ha non!

Il FAUT utiliser Dispose quand il est present sur un objet IDisposable, c’est obligatoire. Si tu le fais pas je viens chez toi la nuit et je te tatoue IDisposable sur le front et je met un sceau d’eau par la tete pour te reveiller.

Apres un Dispose, l’objet est toujours valable cela dit, il est vivant, il y a aucun probleme, sauf que toutes les attaches/relations a des ressources natives qu’il pouvait avoir ont ete coupees/suprimees/ejectees/enlevees. Donc l’objet est 99 fois sur 100 inutilisable et le seul moyen de s’en sortir ca serait d’en recreer un nouveau, mais c’est orthogonal au garbage collector. Un objet disposed qui est toujours reference quelque part ne sera pas ramasse par le GC. En general il est devenu une coquille vide qui pese pas lourd (un objet IDisposable etant souvent un wrappeur autour d’une ressource native qui, elle, pese lourd) mais c’est quand meme le cas…

Voila, j’espere que c’est plus clair.

Voilà, c’est juste la réponse que je cherchais. Mon = Nothing est donc nécessaire puisque je teste l’objet dans mon code à différent endroits.
Vous êtes allé trop loin, je pensais pas du tout au GC.
Par contre, là je vais me coucher, et j’espère pas trop cauchemarder d’un Glop tatoueur de l’ombre…

Bon, après, cela dit, si tu oublies le dispose, ce qui est super crade, avant de déréférencer l’objet, l’objet va généralement s’auto-disposer quand le GC va passer par là. Mais c’est gaspillage de ressources.

Oui, l’objet va essayer de faire de son mieux pour nettoyer comme il faut sur le thread du finalizer, mais c’est pas garanti du tout qu’il y arrive et ca plombe le thread de finalizer a faire des operations potentiellement lourdes, ce qui a tendance a encourager la promotion de medium lived objects dans des generations de garbage collection ou ils ont rien a faire ce qui a plein de mauvaise consequences sur les perfs, etc, etc. C’est le mal. C’est la mesure de la derniere chance pour tenter de s’en sortir quand meme. Faut pas se reposer dessus, ne serais ce que parceque je tatoue le front des gens qui font ca :stuck_out_tongue:

Tout ça, ce n’est qu’une histoire de thread alors :stuck_out_tongue: Histoire que l’objet libère les ressources dans le bon thread.

Mais pour le Objet = Nothing, on ne l’utilise rarement, si c’est une variable de méthode, l’objet sera supprimé automatiquement à la fin de la méthode si c’est une propriété de classe l’objet sera supprimé lorsqu’on supprimera l’objet « conteneur » (dans le cas où il n’y a qu’une seule et unique référence bien entendu). La seul fois où on peut (doit) faire des = Nothing, c’est pour les classes qui représentent des listes, piles, map, … mais je peux me tromper, vu qu’en VBA, je préfère mettre des = Nothing par tout au cas où, car Excel, niveau gestion de la mémoire, c’est CACA, et en Java, je laisse toujours le GC faise son TAF.

J’en profite pour rappeler une syntaxe méconnue en C# (je ne connais pas l’équivalent VB.Net désolé) spécialement utilisée pour les objets implémentant IDisposable :

public void AMethodThatUsesSomeDisposableResources { try { using(IDbConnection conn = SomeDbConnectionFactory.CreateConnection()) { conn.Open(); using(IDbCommand comm = conn.CreateCommand()) { comm.CommandText = "Drop database master"; //;D comm.ExecuteNonQuery(); } } } catch(...) { ... } }

Les avantages :

  1. c’est beauuuuuuu…
  2. Même si y’a un bout de code qui pete une exception, on est certain que la commande et que la connexion seront bien fermées. (la méthode Dispose étant appelée à la fin du scope du using)
  3. c’est vrai que c’est beauuuuu…

les incovénients :

  1. Attention, en cas de code spagethi, un écran 16/9e peut trouver son utilité :stuck_out_tongue:
  2. Les gens peu rigoureux peuvent se foirer dans les accolades…