7
votes

Disposer () ou ne pas disposer () éléments dans un tableau d'objets isisposables?

Il existe de nombreux exemples de tableaux ou de listes d'objets isisposables retournés des fonctions de .NET. Par exemple, processus.getprocesses () .

  • Si j'appelle cette méthode, c'est ma responsabilité de disposer () de tous les membres de la matrice comme je l'ai itérair?
  • Pourquoi devrait-il être ma responsabilité puisque je n'ai jamais créé les objets et que la matrice que j'ai reçue est juste des pointeurs sur les objets créés en dehors de mon code.

    J'ai toujours pensé que c'était le fardeau du créateur de disposer (). Alors quelle est la règle appropriée ici?


4 commentaires

Il n'y a aucun moyen pour le Créateur pour les éliminer ou les pièces à l'intérieur des cours car il n'y a pas de destructeur. Ils ne contrôlent pas de vous définir une variable à rien pour ne pas disposer de l'objet ou du contenu qui nécessitent une disposition.


Bien sûr, vous pouvez, pour process.getprocesses (), vous pouvez conserver un tableau interne de tous les objets de processus () que vous êtes jamais revenus aux appelants, puis vérifiez périodiquement si vous êtes le seul qui a une référence à l'objet et si le cas étrait-il ()


@Denis déterminant si quelqu'un d'autre a une référence à ce que vous pouvez réellement faire.


Déterminer si quelqu'un d'autre a une référence n'est pas quelque chose que vous devez faire. L'objet de processus suit des métadonnées sur un processus et non le processus lui-même. Vous pouvez disposer d'un processus lorsque vous avez terminé de poser ses métadonnées; Cela ne fera pas la sortie du processus. Vous pouvez appeler le processus.getprocesses deux fois, tout disposer à partir du premier appel et les processus du deuxième appel fonctionneront toujours comme prévu sans lancer une extrémitéDisposedException.


4 Réponses :


-1
votes

La règle est très simple: si vous pensez que d'autres programmes utiliseront votre iDisposables , alors ne les détruisez pas. Sinon, faites-le.

Par exemple: GetProcesses () Renvoie d'autres processus utilisés par d'autres programmes, de sorte que vous ne devriez pas disposer eux.

De l'autre côté, les fichiers que vous avez ouverts doivent être libérés pour d'autres processus du système d'exploitation, de sorte que vous devriez clôturer et éliminer les flux de wrapper au-dessus d'eux (disons, vous devez disposer Steam renvoyé par Fichier.open méthode).

Mise à jour :
de MSDN :

  • do implémenter le modèle de base éliminer les types contenant instances de types jetables. Voir la section Dispose de base pour plus de détails sur le modèle de base. Si un type est responsable de la Durée de vie d'autres objets jetables, les développeurs ont besoin d'un moyen de disposer d'entre eux aussi. L'utilisation de la méthode de jet de conteneur est une manière commode rendre cela possible.
    • do implémenter le modèle de base éliminer et fournir un finaliseur sur les types de maintien des ressources qui doivent être libéré explicitement et cela n'a pas de finaliseurs.
      Par exemple, le motif doit être mis en œuvre sur des types stockant des tampons de mémoire non gérés. La section Types de taille finalisable traite des lignes directrices relatives à Mise en œuvre des finaliseurs.
    • considère mettre en œuvre le modèle de base éliminer les classes qui ne tiennent pas des ressources non gérées ni des objets jetables, mais sont susceptibles d'avoir des sous-types qui font.

4 commentaires

Mais si je ne les détruis pas, je laisse des poignées flottantes ... alors devrais-je les détruire? Pensez-vous que les objets de processus () renvoyés sont partagés. Je parie qu'ils sont nouvellement créés pour chaque demande de process.getprocesses () et si vous ne vous disposez pas d'avoir probablement une fuite de la poignée ...


Processus - Non, vous ne devriez pas (si vous ne les créez pas). Images ou fichiers ou autres choses comme celle-là - oui, vous devriez.


"Je laisse des poignées flottantes autour" - ils seront finalisés, donc c'est bon


Je crois qu'il est sûr d'appeler Disposer sur un processus que vous obtenez de getProcesses () . La documentation stipule que crée une gamme de nouveaux composants de processus et les associe aux ressources de processus existantes. Celles-ci ne seront pas utilisées par d'autres programmes et les élimineront d'eux n'effaceront pas les processus qu'ils représentent.



8
votes

Il n'y a pas de règle générale. Cela dépend de la situation et de la manière dont la méthode en question est conçue pour savoir si "vous" êtes responsable de l'élimination des objets que vous avez accès. C'est là que la documentation est souvent importante pour aider les utilisateurs du type à comprendre leurs responsabilités.

J'ai toujours pensé que c'était le fardeau du Créateur de Dispose ()

Cela ne peut pas être strictement vrai. Il est parfois que le cas qu'un objet jetable, vivra la durée de vie du bloc de code la créant. Bien que ce soit le plus simple lorsque le créateur peut disposer de l'objet, parfois il est tout simplement impossible pour eux de pouvoir. Lors du retour d'un objet jetable à partir d'une méthode est une situation où elle n'est souvent pas possible pour le code créant l'objet jetable pour la nettoyer, car sa vie doit être plus petit que la durée de vie de l'objet jetable .


6 commentaires

Je peux créer un objet jetable en instanciant l'un dans la déclaration d'un bloc d'utilisation. Un bloc d'utilisation ne serait-il pas exactement ce qui résout cela? La durée de vie de l'appel de méthode Création de l'objet jetable est plus petite que l'objet jetable actuel lui-même ...? Si ce n'est pas le cas et que je manque du point, pourrais-je vous convaincre d'ajouter un exemple (même un artificiel) à votre réponse?


Gosh, je ne lis pas la documentation qui soit soigneusement pour chaque classe que j'utilise. Tu es sûr qu'il n'y a pas de règle?


@Denis, non, il n'y a personne de règle pour cette situation. Vous devriez décider par vous-même.


@WIMOMOMBELET Lors de la création d'un objet jetable à partir d'une méthode de la vie de la vie est plus grande que la durée de vie de l'objet jetable, vous pouvez utiliser un en utilisant , et tout va bien. Lorsque l'objet jetable doit vivre la méthode qui le déclare (comme tend à se produire lorsque vous le retournez de la méthode), un en utilisant ne aide pas).


@Denis Si le type est jetable et que vous ne savez pas si vous devez en disposer ou non, alors vous devez vérifier la documentation. Comme il est assez rare d'avoir des méthodes qui renvoient des objets jetables en premier lieu, cela ne vient pas réellement tout cela souvent.


@Servy, je dirais que ce n'est pas si rare que des méthodes de retour d'une jetables (flux, sessions, ...), mais une collection de jetables comme dans les ops getprocesses est certainement exceptionnel. La seule règle «générale» quant à qui est responsable de l'élimination, puis est déterminée par l'OMS considérée comme le propriétaire de la ressource, qui serait dans la plupart des cas le client demandant la ressource.



2
votes

avec relativement peu d'exceptions près (la plupart d'entre elles pourraient être décrites comme des approches de moindre des maux pour traiter avec un code mal conçu qui ne peut pas être modifié), chaque instance iDisposable doit à un moment donné. Le moment est exactement un propriétaire bien défini. Dans les cas où une méthode renvoie quelque chose d'un type qui implémente Idisposable , le contrat de la méthode précisera si la méthode est renoncée à la propriété (auquel cas l'appelant doit s'assurer que l'objet est disposé - soit en éliminant l'objet lui-même ou renoncer à la propriété à quelqu'un d'autre), ou si la méthode renvoie simplement une référence à un objet qui appartient à quelqu'un d'autre .

Dans le code correctement écrit, la question de savoir si un objet doit ou non être disposé est rarement un jugement appeler . Le propriétaire d'un objet devrait s'assurer qu'il est éliminé; personne d'autre ne devrait le disposer. De temps en temps, il peut être nécessaire d'accepter une méthode d'accepter un paramètre indiquant si la méthode devrait transférer la propriété d'un Idisposable . Par exemple, si le code veut créer un son, transmettez-le à une méthode "Démarrer la lecture du son" et ne veut jamais faire face à ce son, il peut être le plus pratique d'avoir le code pour jouer au son d'accepter et de disposer le Son quand c'est fait; Si le code veut être capable de jouer un son à plusieurs reprises, cependant, et veillera à ce que l'objet sonore restera en vie aussi longtemps que nécessaire, il serait plus pratique du code de jeu sonore pas prendre possession. L'utilisation de méthodes distinctes peut être plus propre, mais à l'aide d'un paramètre peut facilormir l'encapsulation.

En règle générale, lorsque le code renvoie une liste d'objets qui implémentent Idisposable , le but du code est de identifier les objets sans transporter aucun intérêt de propriété. En l'absence d'intérêt de propriété, le code recevant une telle liste devrait pas appel jetez dessus.


0 commentaires

1
votes

La méthode getProcesses n'alloue pas de poignées (ou d'autres ressources non gérées) dans les instances de processus renvoyées.

Seulement si vous appelez certaines méthodes sur les instances de processus renvoyées sont des poignées créées, dans presque tous les cas, ils sont libérés avant de renvoyer (par exemple, processus.kill ).

Par conséquent, il est totalement inutile dans la plupart des situations de disposer de chaque processus instance de processus renvoyé.


1 commentaires

Pourriez-vous développer votre argument? Documentation est assez adontif que vous devriez.