Classes telles que Stream
, StreamReader
, StreamWriter
etc outils IDisposable
interface. Cela signifie que nous pouvons appeler la Dispose()
méthode sur les objets de ces classes. Ils ont également défini une public
méthode appelée Close()
. Maintenant, cela me trouble, que dois-je appeler une fois que j'ai fini avec les objets? Et si j'appelle les deux?
Mon code actuel est le suivant:
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 des using()
constructions, qui appellent automatiquement la Dispose()
méthode sur chaque objet. Mais j'appelle aussi des Close()
méthodes. Est ce juste?
Veuillez me suggérer les meilleures pratiques lors de l'utilisation d'objets de flux. :-)
L'exemple MSDN n'utilise pas les using()
constructions et la Close()
méthode d' appel :
Est-ce bien?
using (MemoryStream ms1 = new MemoryStream(), ms2 = new MemoryStream()) { }
. Je veux dire comme ça où vous pouvez redéfinir le type:using (MemoryStream ms = new MemoryStream()) using (FileStream fs = File.OpenRead("c:\\file.txt")) { }
Réponses:
Un saut rapide dans Reflector.NET montre que la
Close()
méthode surStreamWriter
est:Et
StreamReader
c'est:Le
Dispose(bool disposing)
remplacement dansStreamReader
est:La
StreamWriter
méthode est similaire.Ainsi, en lisant le code, il est clair que vous pouvez appeler
Close()
etDispose()
diffuser des flux aussi souvent que vous le souhaitez et dans n'importe quel ordre. Cela ne changera en rien le comportement.Il s'agit donc de savoir s'il est ou non plus lisible à utiliser
Dispose()
,Close()
et / ouusing ( ... ) { ... }
.Ma préférence personnelle est que cela
using ( ... ) { ... }
devrait toujours être utilisé lorsque cela est possible car cela vous aide à "ne pas courir avec des ciseaux".Mais, bien que cela contribue à l'exactitude, cela réduit la lisibilité. En C #, nous avons déjà une pléthore d'accolades fermantes, alors comment savoir laquelle effectue réellement la fermeture sur le flux?
Donc je pense qu'il est préférable de faire ceci:
Cela n'affecte pas le comportement du code, mais facilite la lisibilité.
la source
Close()
appel redondant . Si quelqu'un moins expérimenté regarde le code et ne le sait pas,using
il: 1) le recherchera et l' apprendra , ou 2) ajoutera aveuglément unClose()
manuellement. S'il choisit 2), peut-être qu'un autre développeur verra le redondantClose()
et, au lieu de "rire", instruira le développeur le moins expérimenté. Je ne suis pas en faveur de rendre la vie difficile aux développeurs inexpérimentés, mais je suis en faveur de les transformer en développeurs expérimentés.Non, vous ne devez pas appeler ces méthodes manuellement. A la fin du
using
bloc laDispose()
méthode est automatiquement appelée ce qui prendra soin de libérer les ressources non managées (au moins pour les classes standard .NET BCL telles que les flux, les lecteurs / écrivains, ...). Vous pouvez donc également écrire votre code comme ceci:La
Close()
méthode appelleDispose()
.la source
using
le premierresponseStream
car cela est enveloppé par lereader
qui s'assurera qu'il est fermé lorsque le lecteur est éliminé. +1 nonthelessThe Close method calls Dispose.
... et dans le reste de votre message, vous laissez entendre queDispose()
cela appelleraitClose()
, je ne devrais pas appeler ce dernier manuellement. Êtes-vous en train de dire qu'ils s'appellent?using
bloc. J'implémente une classe qui écrit de temps en temps et qui ne le peut donc pas.using
(ou, encore une fois, opter pour le Dispose Pattern).La documentation dit que ces deux méthodes sont équivalentes:
Donc, les deux sont également valables:
Personnellement, je m'en tiendrai à la première option, car elle contient moins de "bruit".
la source
Sur de nombreuses classes prenant en charge les deux méthodes
Close()
etDispose()
, les deux appels seraient équivalents. Sur certaines classes, cependant, il est possible de rouvrir un objet qui a été fermé. Certaines de ces classes peuvent conserver certaines ressources actives après une fermeture, afin de permettre la réouverture; d'autres peuvent ne garder aucune ressource activeClose()
, mais peuvent activer un drapeauDispose()
pour interdire explicitement la réouverture.Le contrat pour
IDisposable.Dispose
exige explicitement que l'appeler sur un objet qui ne sera plus jamais utilisé sera au pire inoffensif, donc je recommanderais d'appeler l'unIDisposable.Dispose
ou l' autre ou une méthode appeléeDispose()
sur chaqueIDisposable
objet, que l'on appelle également ou nonClose()
.la source
C'est une vieille question, mais vous pouvez maintenant écrire en utilisant des instructions sans avoir à bloquer chacune d'elles. Ils seront éliminés dans l'ordre inverse lorsque le bloc contenant est terminé.
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/using
la source