Question

Le collecteur des ordures libérerait-il automatiquement le Ressources non gérées (peu importe, en fait) associé à certains IDisposable Instance si, par exemple, j'ai oublié d'écrire using déclaration?

Évidemment, je ne sais pas Quand cela se produirait, mais est-ce bien de quitter le IDisposable au GC Quand je ne me soucie pas de ces ressources et que je suis d'accord avec cela, ils seront disposés finalement?

Était-ce utile?

La solution

Le collecteur des ordures libérerait-il automatiquement les ressources non gérées (peu importe, en fait) associées à une instance iDisposable si, par exemple, j'ai oublié d'écrire en utilisant une instruction?

Habituellement, mais pas nécessairement. L'auteur d'une ressource jetable doit faire la bonne chose.

De toute évidence, je ne sais pas quand cela se produirait, mais est-ce bien de laisser l'IDisposable au GC alors que je ne me soucie pas de ces ressources et je suis d'accord avec le fait qu'ils seront finalement disposés?

Votre question présuppose un mensonge. Le collecteur de déchets n'appelle jamais, jamais disposer. Au contraire, le collecteur des ordures appelle le destructeur (ou "finalizer" si vous préférez). C'est le destructeur qui pourrait ou non appeler Disser pour l'utilisateur oublieux.

Votre question indique également une mauvaise attitude. Tu Peut-être ne pas se soucier si les ressources sont libérées en retard, mais un autre programme pourrait certainement s'en soucier! Et si votre client fonctionne deux Des programmes qui essaient à la fois d'accéder à la même ressource non gérée, une écrite par vous et une écrite par quelqu'un d'autre? Être un bon citoyen; Libérez vos ressources rares dès que vous en avez terminé afin que d'autres programmes puissent les utiliser. C'est le véritable but de «l'utilisation» - c'est pour être poli en veillant à ce que les ressources rares soient récupérées rapidement.

Une mise en œuvre correcte du modèle DISSOSE garantira que le destructeur nettoie les ressources non gérées si l'utilisateur oublie d'appeler disposer, et garantira que le destructeur ne nettoie pas les ressources s'ils s'en souviennent.

Si vous êtes la personne qui rédige la mise en œuvre de Disser pour une classe qui possède des ressources non gérées Il est de votre responsabilité de faire en sorte que le code destructrice soit correct dans le cas où l'utilisateur ne appelle pas correctement. La bonne façon d'écrire ce code est extrêmement bien documentée; suivre le modèle. Voir les commentaires de Jon pour quelques liens utiles.

Notez également que si vous écrivez une telle classe, vous devez également le faire fonctionner dans des scénarios dans lesquels il est impossible Pour que l'utilisateur appelle Disser. Par exemple, supposons que le constructeur alloue deux ressources non gérées, et entre l'allocation de la première et du deuxième, une exception est lancée et rattrapée à l'extérieur du constructeur. Il n'y a donc aucun moyen pour l'utilisateur de s'appeler disposer parce que l'affectation de la nouvelle référence d'objet se produit après la réussite du constructeur, et le constructeur n'a jamais fini de fonctionner avec succès. Comment la première ressource non gérée est-elle libérée? Seul le destructeur peut le libérer. Le destructeur doit être robuste face à de tels scénarios; L'objet destruction n'a peut-être jamais été entièrement construit, vous ne pouvez donc pas compter sur un invariant du constructeur.

Autres conseils

Oui, ils seraient finalement nettoyés. Vous n'avez qu'à utiliser using (heh ..) Lorsque vous avez besoin d'un nettoyage déterministe des ressources, comme pour GDI, SQL et autre code basé sur la poignée du système, ou pour des objets potentiellement lourds de mémoire comme DataTable.

EDIT: Cela suppose que vous avez implémenté le Dispose Modèle correct et avez votre appel destructeur Dispose.

Si un objet implémente correctement l'interface iDisposable, en incluant un appel conditionnel à la méthode de disposition dans le finalizer, le GC déclenchera l'élimination de l'objet lors d'une collection (via le finalizer).

Il y a des choses qui font que cela ne se produit pas, mais si le modèle standard est suivi, cela devrait fonctionner dans la plupart des cas.

Si l'objet n'inclut pas le code d'élimination dans le finalizer, tous les paris sont désactivés. Les ressources non gérées peuvent rester non disposées jusqu'à ce que les supernovas du soleil.

Non pas forcément. Cela dépend de la façon dont vous avez les ressources non gérées.

Si vous avez un poignée directe aux ressources non gérées (probablement un IntPtr) Ensuite, vous devez avoir un finalizer ou utiliser SafeHandle... sinon vous définitivement pourrait divulguer des ressources non gérées.

Si votre type a juste une référence à quelque chose comme un FileStream, alors tu devrais s'attendre à ce ce Type aura un finalizer.

Maintenant, il est assez rare d'avoir un accès direct à des ressources non gérées à partir de votre type, et si vous utilisez des types de framework, ils devraient vraiment nettoyer de manière appropriée (mais non déterministe). Pourtant, c'est possible.

N'importe quel IDisposable Dans le système, les bibliothèques se disposeront lors de la finalisation (ou du moins, prendra la plupart des mêmes étapes que le ferait de disposition).

Il n'y a aucune garantie sur des trucs tiers - si vous utilisez une interface à une bibliothèque C qui vous donne des poignées, par exemple, ces poignées pourraient ne pas être nettoyées jusqu'à ce que la bibliothèque soit déchargée (ce qui a tendance à se produire uniquement à la sortie de l'application ). Mais c'est assez courant pour oublier d'utiliser Dispose ou using (ou pour ne même pas savoir ou se soucier qu'un certain type est jetable), que toute bibliothèque .NET qui ne le rendait pas compte est assez mal écrite, IMO.

Lorsqu'un objet est créé, s'il remplace l'objet.Finalize, le système l'ajoutera à une liste d'objets avec des finalisateurs enregistrés. Les objets de cette liste, et les objets directement ou indirectement référencés par eux, seront inadmissibles à l'élimination, sauf si GC.SuppressFinalize les est appelés, ou ils sont autrement supprimés de la liste. Si le système remarque qu'un tel objet serait éligible à l'élimination Mais pour son existence sur la liste des objets finalisables, le système supprimera si la liste des objets avec des finalisateurs enregistrés et l'ajoutera à une liste d'objets qui devraient avoir leur routine finalisée appelée dès que pratique. Chaque fois que cette dernière liste n'est pas vide, le système exécutera les routines finalisées des objets là-bas.

Notez que le collecteur de déchets ne dissient rien - tout ce qu'il fait est d'appeler la routine finalisée des objets qui se sont inscrits à la finalisation. Bien que de nombreux types d'objets aient finalisé les routines qui peuvent assurer le nettoyage si elles sont abandonnées à tort, la finalisation peut être lourde de péril. Les objets seront rarement finalisés exactement au bon moment; Ils ne seront souvent finalisés que longtemps après avoir été abandonnés, et dans certains cas, ils peuvent être finalisés Alors que leurs ressources sont toujours utilisées. Il est donc sage d'éviter de compter sur les finalisateurs. Il y a des occasions où cela est nécessaire, mais ils sont presque toujours maculés.

BTW, notez que si les objets d'une certaine classe s'abonnent directement aux événements d'objets avec une durée de vie plus utile, ni les anciens objets (abonnés à l'événement), ni aucun objet auxquels ils n'ont des références directes ou indirectes, deviendront éligibles à l'élimination ou à la finalisation Jusqu'à ce que ces derniers objets le fassent. Bien que l'on puisse affirmer que toutes les classes devraient nettoyer après elles-mêmes s'ils sont abandonnés, s'assurer qu'un abonné d'événement peut découvrir que cela a été abandonné nécessite la création et l'utilisation d'objets enveloppe. Cela ajoutera une complexité considérable et entravera les performances dans le cas où la classe est utilisée correctement. Essayer de nettoyer les événements avec un finalizer lorsque ne pas utiliser d'objets wrapper serait inutile; La classe avec des événements pendants ne serait pas éligible à la collection tant que l'éditeur d'événements est devenu éligible, et une fois que cela s'est produit, peu importe si l'ancienne classe s'est inscrite ou non.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top