Dois-je appeler Close() ou Dispose() pour les objets de flux?
Classes telles que Stream
, StreamReader
, StreamWriter
etc implémente IDisposable
interface. Cela signifie que nous pouvons appeler Dispose()
méthode sur des objets de ces classes. Ils ont également défini un public
méthode appelée Close()
. Maintenant que me confond, à quoi dois-je appeler une fois que je suis fait avec des objets? Que faire si je appeler?
Mon code actuel est: est-ce
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
using (StreamWriter writer = new StreamWriter(filename))
{
int chunkSize = 1024;
while (!reader.EndOfStream)
{
char[] buffer = new char[chunkSize];
int count = reader.Read(buffer, 0, chunkSize);
if (count != 0)
{
writer.Write(buffer, 0, count);
}
}
writer.Close();
}
reader.Close();
}
}
Comme vous le voyez, j'ai écrit using()
des constructions, qui appelle automatiquement Dispose()
méthode sur chaque objet. Mais j'ai aussi appeler Close()
méthodes. Est-il juste?
Merci de me suggérer les meilleures pratiques lors de l'utilisation d'objets de flux. 🙂
MSDN exemple ne pas utiliser using()
constructions, et d'appeler Close()
méthode:
Est-il bon?
- Si vous êtes à l'aide de ReSharper vous pourrait la définir comme une "antipattern" dans la formulation de catalogue. ReSharper marquera chaque utilisation d'erreur/indicateur/avertissement quant à votre définition. Il est également possible de définir la façon dont ReSharper est d'appliquer un QuickFix pour un tel événement.
- Juste un conseil: Vous pouvez utiliser l'instruction à l'aide comme ça pour plusieurs jetables itens: à l'aide de flux (Stream responseStream = réponse.GetResponseStream()) using (StreamReader reader = new StreamReader(responseStream)) à l'aide de (StreamWriter writer = new StreamWriter(filename)) { //...code }
- double possible de Ne Stream.Disposer toujours d'appel de Flux.De près (et de Flux.Flush)
- Vous n'avez pas besoin de votre nid à l'aide des déclarations comme ça, on peut les empiler l'un sur l'autre et ont une série de crochets. Sur un autre post, j'ai proposé une modification pour un extrait de code qui devrait avoir l'aide d'instructions avec cette technique si vous souhaitez regarder et corriger votre code de "flèche": stackoverflow.com/questions/5282999/...
- Vous avez à votre nid
using
ce genre de déclaration.using
permet à un seul type, même si vous sont en cours d'initialisation des ressources multiples dans la même instruction. Si vous utilisez plusieurs états ou de plusieurs types, par définition, vous devez nidusing
états; ici, les objets sont de types différents et doivent être dans desusing
consolidés. - Vous pouvez avoir plusieurs à l'aide de relevés, mais pas les imbriquer et au lieu de les empiler. Je ne parle pas de la syntaxe comme ce qui limite le type:
using (MemoryStream ms1 = new MemoryStream(), ms2 = new MemoryStream()) { }
. Je veux dire que c'est là où vous pouvez redéfinir le type:using (MemoryStream ms = new MemoryStream()) using (FileStream fs = File.OpenRead("c:\\file.txt")) { }
- Désolé d'être pointilleux, mais ceux-ci déclarations sont imbriqués.
Vous devez vous connecter pour publier un commentaire.
Un saut rapide dans Reflector.NET montre que la
Close()
méthode surStreamWriter
est:Et
StreamReader
est:La
Dispose(bool disposing)
remplacer dans leStreamReader
est:La
StreamWriter
méthode est similaire.Ainsi, la lecture du code, il est clair que vous pouvez appeler
Close()
&Dispose()
sur les cours d'eau aussi souvent que vous le souhaitez et dans n'importe quel ordre. Il ne changera pas le comportement en aucune façon.De sorte qu'il se résume à savoir si ou non il est plus lisible d'utiliser
Dispose()
,Close()
et/ouusing ( ... ) { ... }
.Ma préférence personnelle est que
using ( ... ) { ... }
doit toujours être utilisé lorsque c'est possible qu'il vous aide à "ne pas courir avec des ciseaux".Mais, tout cela contribue à l'exactitude, il n'réduire la lisibilité. En C#, nous avons déjà pléthore de fermeture des accolades alors, comment savons-nous lequel on effectue la fermer sur le stream?
Donc je pense qu'il est préférable de faire cela:
Il n'a pas d'influence sur le comportement du code, mais il ne l'aide lisibilité.
Close
et y compris leClose
est bénigne car elle ne permet pas de changer les comportements.using
efficacement ferme le flux de sorte qu'il semble que je suis la fermeture de deux fois - mais encore une fois vous avez de l'expérience, de sorte que vous savez que ce n'est pas grave si je le fais. Cependant, si quelqu'un de moins expérimenté regarde le code, il pourrait penser qu'il n'était pas fermé à moins queClose
a été explicitement demandé. Ce modèle rend la programmation plus sûr pour les développeurs inexpérimentés et donne juste développeurs expérimentés d'un "rire". 🙂Close()
appel. Si quelqu'un de moins expérimenté regarde le code et ne savent pas à propos deusing
il devra: 1) rechercher et apprendre, ou 2) à l'aveuglette ajouter unClose()
manuellement. S'il choisit 2), peut-être une autre développeur de voir la redondantClose()
et au lieu de "rire sous cape", charger les moins expérimentés développeur. Je ne suis pas en faveur de rendre la vie difficile pour les développeurs inexpérimentés, mais je suis en faveur de les transformer en de développeurs expérimentés.Using
est facultatif et de toute façon, à mon humble avis, il peut ou peut ne pas être pratique à utiliser, en fonction des circonstances et des préférences personnelles. En l'utilisant, ajoute un de plus le bloc de code qui est inutile si vous l'avez explicitement disposer vos objets.Dispose
. Je pense que leusing
mot-clé est assez explicite. Aussi à l'aide de ajoute automatiquement dans untry
/catch
, qui garantit que le dispose est appelé. Il change réellement la sémantique pour le mieux, je pense.Non, vous ne devriez pas appeler ces méthodes manuellement. À la fin de la
using
bloc de la méthode dispose est automatiquement appelé, qui prendra soin de libérer des ressources non managées (au moins pour la norme .NET BCL classes, comme les ruisseaux, les lecteurs/écrivains, ...). Ainsi, vous pouvez également écrire votre code comme ceci:La clôture des appels à la méthode Dispose.
using
la premièreresponseStream
depuis que est enveloppé par lereader
qui est sûr de faire son fermé lorsque le lecteur est disposé. +1 néanmoinsThe Close method calls Dispose.
.. et dans le reste de votre post, vous êtes ce qui implique queDispose()
appelleraisClose()
, je ne devrais pas appeler le dernier manuellement. Êtes-vous en disant qu'ils s'appellent les uns les autres?using
bloc. Je suis l'implémentation d'une classe qui écrit de temps à autre et, par conséquent, ne peut pas.using
(ou, encore une fois, optez pour le Modèle dispose).La documentation dit que ces deux méthodes sont équivalentes:
Donc, ces deux sont tout aussi valables:
Personnellement, je m'en tiendrais à la première option, car il contient moins de "bruit".
Sur de nombreuses classes qui soutiennent à la fois Proche et de Disposer de méthodes, les deux appels serait équivalent. Sur certaines classes, cependant, il est possible de ré-ouvrir un objet qui a été Fermer avais. Certains de ces classes peut garder quelques ressources en vie après un Proche, afin de permettre la réouverture; d'autres ne peuvent pas garder toutes les ressources vivantes sur Fermer, mais peut définir un indicateur sur Disposer d'interdire explicitement la ré-ouverture.
Le contrat pour IDisposable.Disposer exige explicitement que de l'appeler sur un objet qui ne seront jamais utilisées sera, au pire, à couvert, donc je vous conseille de l'appel de l'une IDisposable.Jetez-les ou une méthode appelée Disposer sur chaque IDisposable objet, si oui ou non on appelle également à Proximité.