2009-11-23 6 views
2

En supposant que j'ai une méthode dans mon modèle d'architecture de commande qui modifie le contenu du chemin graphique comme ceci: (GraphicsPath IDisposable)Vous devez disposer des objets IDisposable avant de les repeupler?

(ce qui est purement un exemple non testé, rapide)

public void DoSomething(ref GraphicsPath path) 
{ 
    if(path != null) 
     { 
     List<PointF> pts = new List<PointF>(); 
     foreach(PointF pt in path.PathPoints) 
     { 
     //again, just a silly example. 
     float y = pt.X; 
     float x = pt.Y; 
     pts.Add(new PointF(x, y)); 
     } 
    path.Dispose(); //<-- Do I need this? 
    path = new GraphicsPath(pts.ToArray(), path.PathTypes); 
    } 
} 

Do I besoin de disposer le chemin avant de définir le chemin égal au nouveau chemin? Si oui, pourquoi?

+2

Votre question a déjà reçu une réponse, mais la conception globale n'est pas une bonne pratique. Les paramètres de référence en général sont une odeur de code. Envisager de refactoring, peut-être à GraphicsPath DoSomething (chemin GraphicsPath). – TrueWill

+0

Un changement qui à un « GraphicsPath DoSomething (entrée GraphicsPath) », et que le Éliminez de l'appelant de l'objet lui-même. Je (personnellement) n'aime pas ref/out, et il est souvent possible de réécrire un tel code en code qui n'utilise pas ref/out. – sisve

+1

Je suis entièrement d'accord avec TrueWill. Puisque vous détruisez une instance et en créez une autre, un paramètre 'ref' est au mieux ambigu. Si vous changez votre signature de méthode pour 'GraphicsPath DoSomething (chemin GraphicsPath)' vous pouvez laisser à l'appelant de vous assurer que le 'GraphicsPath' est disposé (avec un bloc' using', par exemple). –

Répondre

8

Oui. Puisque vous transmettez la variable de chemin par référence, vous "orphelin" l'instance précédente lorsque vous la réattribuez. Nettoyer avec Dispose() est la bonne chose à faire.

+0

+1, j'ajouterais que le chemin devrait être dans un 'using block', moins l'assignation. – user7116

+0

@sixlettervariables: Mais il ne peut pas être dans un bloc 'using', parce que la variable' path' est passée en entrée et en sortie en argument 'ref'. C'est pourquoi plusieurs commentaires préconisent une signature de méthode différente. –

+2

IMHO la réponse n'est pas aussi simple que cela. Vous supposez que le code appelant n'aura plus besoin de la référence. Ce n'est pas certain. Cependant, finalement, je considère que la conception de la fonction est erronée. –

0

Ouais, vous devriez probablement.

Si l'objet est jetable, cela signifie qu'il a des ressources à nettoyer (comme un fichier ouvert ou une base de données ou autre).

appel disposer, nettoie les vers le haut (dans un monde idéal)

0

Sans discuter le mérite de votre fonction, oui - vous devez appeler Dispose afin que l'objet peut se nettoyer des ressources dont elle a alloué le long du chemin . Une autre raison - au moment où vous lui attribuez quelque chose, vous assumez la responsabilité de sa durée de vie, vous devez donc vous assurer que tout ce qu'il utilisait avant est nettoyé.

4

Il s'agit d'une question difficile à répondre. Si le code consommateur doit être responsable de la gestion de la durée de vie de l'objet, il doit appeler Dispose() à la place de votre code. La raison est que le code pourrait être consommer maintenir une autre référence à l'instance, en plus de celui qu'il a passé à votre code, et il peut attendre de pouvoir continuer à utiliser cette référence après votre méthode a été appelée. Ou, si la sémantique de votre classe indique qu'elle gérera la durée de vie de l'objet une fois qu'il a été passé, alors il devrait appeler Dispose() comme vous l'avez décrit. En règle générale, chaque fois qu'un objet implémente IDisposable, vous devez toujours appeler explicitement sa méthode Dipose() lorsque vous en avez fini (ou utiliser la référence dans un bloc using). Après avoir dit ce qui précède, vous voudrez peut-être revoir votre design car la sémantique qu'il représente n'est pas intuitive.