Pourquoi devrais-je utiliser IDisposable au lieu de l'utiliser en c#?
Aujourd'hui, j'ai voulu effectuer une opération avec un fichier alors je suis venu avec ce code
class Test1
{
Test1()
{
using (var fileStream = new FileStream("c:\\test.txt", FileMode.Open))
{
//just use this filestream in a using Statement and release it after use.
}
}
}
Mais sur la révision du code, on m'a demandé de mettre en œuvre interface IDisposable et de Finaliseur
class Test : IDisposable
{
Test()
{
//using some un managed resources like files or database connections.
}
~Test()
{
//since .NET garbage collector, does not call Dispose method, i call in Finalize method since .net garbage collector calls this
}
public void Dispose()
{
//release my files or database connections
}
}
Mais, ma question est: pourquoi devrais-je ?
Bien que je ne peux pas justifier ma méthodologie selon moi, pourquoi devrions-nous utiliser IDisposable quand à l'aide de déclaration peut se libérer des ressources)
Tout des avantages spécifiques, ou je manque quelque chose ici?
Vous devez uniquement ajouter un finaliseur si vous avez non géré ressources qui devraient être nettoyé. Un
FileStream
est un réussi ressource.OriginalL'auteur now he who must not be named. | 2013-09-02
Vous devez vous connecter pour publier un commentaire.
La réponse donnée par "personne" est correct que
using
bloc ne peut être utilisé pour les classes qui implémentent l'IDisposable
interface et l'explication, c'est parfait. La question à partir de votre côté est "Pourquoi j'ai besoin d'ajouter IDisposable sur la classe de Test et Mais sur l'examen du code, on m'a demandé de mettre en œuvre interface IDisposable et Finalizer méthodes de la classe de Test."La réponse est simple
1) Comme par les normes de codage suivie par de nombreux développeurs, c'est toujours bon de mettre en œuvre
IDisposable
sur les classes qui utilisent des ressources et une fois que le champ d'application de cet objet est plus de la méthode dispose dans cette classe seront assurez-vous que toutes les ressources ont été libérés.2) La classe qui a été écrit n'est jamais telle qu'à l'avenir, aucun changement ne sera apporté et si des modifications sont faites et de nouvelles ressources sont ajoutées ensuite, le développeur sait qu'il a pour la libération de ces ressources dans dispose de la fonction.
Mais Dmitry nous avons toujours des conseils aux développeurs d'ajouter des IDisposable des classes qui utilisent certaines de ressources importantes.
bon explananation. merci. +1
Techniquement, c'est une réponse, mais "modifications futures" est une terrible raison. Sauf si vous avez des fonctionnalités spécifiques à l'esprit que vous êtes assez sûr, sera mis en œuvre il n'y a aucune raison de faire une classe implémente IDisposable, sauf si il en a besoin. Même alors, vous devez être dans une situation où vous ne pouvez pas modifier l'interface de la classe, mais en changeant la mise en œuvre ne va pas être de casser le changement.
La personne qui sera à l'aide de votre classe devra supposer qu'il a des ressources non managées si il utilise l'interface IDisposable. Ensuite, ils devront joindre n'importe quel objet de votre classe dans "l'aide" de l'énoncé (ou d'appeler la méthode dispose) pour s'assurer que leur code n'est pas une fuite des ressources non managées. Si tout le monde faisait cela, indépendamment de l'utilisation de ressources non managées ou pas, toutes les instanciations de classes devrait être enlosed dans "l'aide" des déclarations. Est-ce vraiment une bonne idée de mentir aux utilisateurs de votre classe et de leur dire que votre classe utilise des ressources non managées, quand il ne l'est pas?
OriginalL'auteur dbw
dans votre exemple, à l'aide de déclaration est à droite, parce que vous utilisez des ressources uniquement dans la portée de votre méthode. Par exemple:
mais si les ressources sont utilisées à l'extérieur d'une méthode, alors vous devriez créer de la méthode dispose.
Ce code est faux:
Le droit chose à faire est de mettre en œuvre
IDisposable
pour être sûr que le fichier sera publié une fois qu'il est utilisé.Cette réponse est meilleure que l'a accepté.
OriginalL'auteur Dmitry Dovgopoly
Une petite note d'abord, puisque vous semblez un peu confus sur la façon
using
etIDisposable
interagir les uns avec les autres: La raison pour laquelle vous êtes en mesure de direusing (FileStream fileStream = Whatever()) { ... }
est précisément parce que laFileStream
classe implémenteIDisposable
. Ce que vos collègues ont suggéré, c'est que vous mettre en œuvreIDisposable
sur votre classe de sorte que vous serez en mesure de direusing (Test test = new Test()) { ... }
.Pour ce que ça vaut, je pense que la façon dont vous avez écrit le code d'origine est fortement préférable de la changer, sauf si il y a un peu de raison convaincante pourquoi vous voudrez peut-être garder le
FileStream
ouvert pour l'ensemble de la durée de vie d'unTest1
instance. Une des raisons pour lesquelles cela peut être le cas, c'est que le fichier peut être sujet à changement à partir d'une autre source après le constructeur deTest1
a été appelé, dans ce cas, vous serez coincé avec une ancienne copie des données. Une autre raison de garder leFileStream
ouvert pourrait être si vous souhaitez verrouiller le fichier en cours d'écriture à partir d'ailleurs pendant unTest1
objet est vivant.En général, il est de bonne pratique de libérer des ressources dès que possible, votre code d'origine semble faire. Une chose que je suis un peu sceptique, c'est que le travail est effectué dans votre constructeur au lieu d'une méthode qui est explicitement appelé depuis l'extérieur (explication: http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/). Mais c'est une question tout à fait différente et indépendante de la question de savoir si pour faire de votre classe en œuvre
IDisposable
.Je pense que cette réponse est beaucoup mieux que l'a accepté, que je trouve réellement à confusion.
OriginalL'auteur Magnus Grindal Bakken
Sur la base des informations que vous avez fournies, il n'y a absolument aucune raison de mettre en œuvre
IDisposable
ou un finaliseur surTest
.Seulement de mettre en œuvre un outil de finalisation afin de libérer des ressources non managées (handle de fenêtre, GDI poignée de, poignée de fichier). Vous n'avez généralement pas besoin de faire cela, sauf si vous êtes PInvoking l'API Win32 ou quelque chose. Microsoft a bien enveloppé pour vous dans la
FileStream
de sorte que vous ne avez pas à vous soucier de descripteurs de fichiers.Un finaliseur est destiné à nettoyer des ressources non managées lorsqu'un objet est ordures.
Depuis le garbage collector peut prendre un temps très long avant qu'il ne décide de recueillir votre objet, vous pouvez avoir un moyen de déclencher le nettoyage. Non,
GC.Collect()
est pas la bonne façon de le faire. 😉Pour permettre un nettoyage de ressources autochtones sans avoir à attendre pour le garbage collector, vous mettez en œuvre
IDisposable
sur votre classe. Cela permet à l'appelant de déclenchement de nettoyage sans attendre sur le GC. Ce n' pas cause de votre objet à être libéré par le GC. Il n'est de libérer les ressources indigènes.Dans le cas où un objet est propriétaire d'un autre objet qui est disponible, alors l'objet propriétaire doit également mettre en œuvre
IDisposable
et d'appeler tout simplement l'autre de l'objetDispose()
.Exemple:
Avis que
Tree
ne dispose pas d'un outil de finalisation. Il met en œuvreDispose
, car il doit se soucientApple
de nettoyage.Apple
a un finaliseur pour s'assurer qu'il nettoie laCore
de ressources.Apple
permet aux jeunes de nettoyage en appelantDispose()
La raison pour laquelle vous n'avez pas besoin
Dispose
, et certainement pas besoin d'un finaliseur est parce que votre classeTest
n'est pas propriétaire du champ de membre qui est ou nonIDisposable
. Vous ne vous arrive de créer unFileStream
, qui est jetable, mais vous le "nettoyer" avant de quitter la méthode. Elle n'est pas détenue par leTest
objet.Il existe une exception à cette affaire. Si vous écrivez une classe que vous savez sera héritée par d'autres, et les autres ont à mettre en œuvre
IDisposable
, alors vous devriez aller de l'avant et de mettre en œuvreIDisposable
. Sinon, les appelants ne savez pas de détruire l'objet (ou même être en mesure de sans casting). Cependant, c'est une odeur de code. Habituellement, vous ne serait pas hériter d'une classe et d'ajouterIDisposable
. Si vous le faites, c'est probablement une mauvaise conception.(...) ces Deux sous-classes doivent ajouter IDisposable l'appui, mais les Paramètres de base de classe ne devrait pas. Pourquoi pas? Envisager une autre ressource appelée SomeOtherSettings qui n'utilise pas de ressources gérées. Si vous avez la force de la classe de base pour mettre en œuvre IDisposable, vous avez dit SomeOtherSettings qu'ils ont besoin de s'inquiéter à propos de l'élimination de quelque chose, ce qui signifie qu'ils trop maintenant, à l'appui de IDisposable. Vous avez juste puait le code de la hiérarchie. Voyez ce que je veux dire? Pour moi, c'est la réelle odeur.
oui ça pue pour ajouter
IDisposable
mais il n'est pas vraiment évitable. C'est en raison du Principe de Substitution de Liskov. Si vous avez unSettings
de la classe de base, puis tout consommateur qui accepte les objets de typeSettings
doit également accepter des objets de typeFileSettings
. Maintenant, si leFileSettings
classe exige de nettoyage, comment le consommateur est censé le savoir? C'est pourquoi j'ai évoqué la conversion de type point. SiSettings
sous-classes mettre en œuvreIDisposable
, puis tous les consommateurs qui possède unSettings
objet doit toujours vérifier si l'objet jette àIDisposable
.Lors de la conception de la
Settings
de la classe de base, vous avez défini dans le contrat de la classe. Chaque méthode est une capacité de la classe.IDisposable
est particulier en ce qu'il communique également responsabilités du code appelant. Il est risqué d'ajouter de nouvelles responsabilités pour l'appelant dans les sous-classes, parce qu'alors tout le monde qui fonctionne surSettings
objets a, par magie, savoir à propos de cette possible responsabilité requis par certaines sous-classes. Il est plus sûr de n'ajouter que la responsabilité dans le contrat de la classe de base, afin d'éviter surprenant consommateurs.Je dirais que si l'élimination n'est pas une partie de la classe de base de la responsabilité, que n'importe où que prend celui de la classe de base ne pas le savent parce que ça ne fait pas partie de ce contrat, parfaitement en suivant le principe de Liskov. Le créateur de la sous-classe doit cependant, et parce qu'il serait la création d'une instance de FileSettings. C'est pourquoi je me dois rester avec ma déclaration d'origine c'est plus malodorantes pour ajouter que pas de. Après tout, comment puis-je savoir qui va à la sous-classe des Paramètres et ce qu'ils peuvent ajouter? Dois-je lancer chaque chose possible? Pas de. Alors, pourquoi est-IDisposable différents?
OriginalL'auteur dss539
Réponse courte est que toute la classe qui n'est pas de mettre en œuvre IDisposable ne peuvent pas être utilisés avec de l'aide.
non, il ne peut pas libérer les ressources.
Comme je l'ai écrit ci-dessus que vous avez besoin pour mettre en œuvre IDisposable afin de pouvoir utiliser l'aide. Maintenant, lorsque vous implémentez IDisposable vous obtenez une méthode dispose. Dans cette méthode vous écrire tout le code qui doit prendre soin de toutes les ressources qui doit être éliminé lorsque l'objet n'est plus nécessaire.
L'objectif de l'AIDE est que quand un objet est mis hors de sa portée, il va appeler la méthode dispose et qui est-il.
Exemple
traduira
vous avez utilisé l'aide sur la classe FileStream. pas sur Test1 classe.
Vous êtes à l'aide de "l'aide" pour la FileStream mais vous ne serez pas en mesure d'utiliser "utiliser" pour la classe. Donc je suppose que l'examen signifie que vous devez mettre en œuvre IDisposable pour la classe Test1, afin d'être en mesure d'écrire: à l'aide de(Test1 t = new Test1())
Parce que vous êtes à l'aide de "l'aide" sur FileStream et pas sur Test1
Vous ne pouvez pas faire cela à l'aide de(Test1 t = new Test1()) {}
OriginalL'auteur Ehsan
Je pense que la question est plus comme "puis-je éliminer le fichier immédiatement ou avec la méthode dispose de la classe qui accède à ce fichier?"
Cela dépend: si vous accédez au fichier que dans le constructeur, à mon avis, il n'y a pas de raison de mettre en œuvre la IDisposable. L'aide est la bonne façon
Sinon, si vous utilisez le même fichier aussi dans d'autres méthodes, peut-être que c'est une bonne pratique d'ouvrir le fichier une fois et assurez-vous de fermer votre méthode dispose (mise en œuvre de la IDisposable)
OriginalL'auteur Emanuele