Est-il nécessaire d'envelopper les StreamWriter dans un bloc using?
Il y A quelques jours j'ai posté un peu de code comme ceci:
StreamWriter writer = new StreamWriter(Response.OutputStream);
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
writer.Close();
Response.End();
M'a dit qu'au lieu de cela je doit envelopper StreamWriter en utilisant le bloc dans le cas d'exceptions. Un tel changement permettrait de faire ressembler à ceci:
using(StreamWriter writer = new StreamWriter(Response.OutputStream))
{
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
writer.Close(); //not necessary I think... end of using block should close writer
}
Response.End();
Je ne suis pas sûr pourquoi c'est un changement de prix. Si une exception s'est produite sans l'utilisation de bloc, l'écrivain et la réponse serait toujours nettoyé, droit? Ce qui ne l'aide du bloc de gain de moi?
Vous devez vous connecter pour publier un commentaire.
Nope le flux de rester ouverte dans le premier exemple, étant donné que l'erreur serait nier la clôture de il.
L'aide de l'opérateur forces de l'appel d'Dispose() qui est censé nettoyer l'objet et fermer toutes les connexions ouvertes quand il quitte le bloc.
Je vais donner à l'opinion dissidente. La réponse à la question "Est-il nécessaire d'envelopper les StreamWriter dans un bloc using?" est en fait de Non. En fait, vous ne devrait pas appel Disposer sur un StreamWriter, parce que sa dispose est mal conçu et mal fait quelque chose de mal.
Le problème avec StreamWriter, c'est que, lorsque vous mettez au Rebut, il Dispose le flux sous-jacent. Si vous avez créé le StreamWriter avec un nom de fichier, et il a créé sa propre FileStream en interne, ce comportement serait tout à fait approprié. Mais si, comme ici, on a créé le StreamWriter avec un flux existant, alors ce comportement est absolument quelque Chose de Mal(tm). Mais il le fait quand même.
Ce type de Code ne fonctionne pas:
parce que quand le StreamWriter de
using
bloc Dispose le StreamWriter, qui à son tour jette le ruisseau. Ainsi, lorsque vous essayez de lire à partir du flux, vous obtenez ObjectDisposedException.StreamWriter est une horrible violation de la "nettoyer votre propre désordre de la règle". Il essaye de nettoyer de quelqu'un d'autre désordre, s'ils voulaient ou non.
(Imaginez si vous avez essayé dans la vie réelle. Essayez d'expliquer aux flics pourquoi vous ont fait irruption dans la maison d'autrui et ont commencé à jeter tous leurs trucs dans la poubelle...)
Pour cette raison, je considère StreamWriter (et StreamReader, qui fait la même chose) pour être parmi les très peu de classes où "si elle met en œuvre IDisposable, vous devez Disposer d'appel" est erroné. Jamais appel Disposer sur un StreamWriter qui a été créé sur un flux de données existant. Appeler la méthode Flush() à la place.
Alors assurez-vous de nettoyer le Ruisseau quand vous devriez. (Comme Joe l'a souligné, ASP.NET dispose la Réponse.OutputStream pour vous, donc vous n'avez pas besoin de s'inquiéter à ce sujet ici.)
Avertissement: si vous ne Jetez pas le StreamWriter, alors vous ne besoin d'appeler la méthode Flush() lorsque vous avez terminé l'écriture. Sinon, vous auriez des données sont encore en cours de mis en mémoire tampon, qui n'a jamais fait pour le flux de sortie.
Ma règle pour StreamReader est, faire semblant de ne pas mettre en œuvre IDisposable. Juste le laisser aller lorsque vous avez terminé.
Ma règle pour StreamWriter, appelez Chasse où vous sinon on aurait appelé en Disposer. (Cela signifie que vous devez utiliser un
try
..finally
au lieu d'unusing
.)Emballage de la
StreamWriter
dans unusing
bloc est à peu près équivalent au code suivant:Alors que vous pourriez très bien écrire ce code vous-même, c'est tellement plus facile de le mettre dans un bloc using.
Si une exception se produit sans l'aide du bloc et tue le programme, vous serez à gauche avec openconnections. L'utilisation de bloc sera toujours fermer la connexion pour vous, semblables à si vous étiez à utiliser try{}catch{}finally{}
Finalement, l'écrivain sera nettoyé. Lorsque cela se produit est à la hauteur du garbage collector, qui se rendra compte que la dispose de la commande n'a pas été appelé, et à l'appeler. Bien sûr, le GC peut ne pas fonctionner pendant des minutes, des heures ou des jours en fonction de la situation. Si l'écrivain est la tenue d'un verrou exclusif sur le dire, un fichier, aucun autre processus ne sera capable de l'ouvrir, même si vous êtes à la longue fini.
L'aide du bloc assure de Disposer de l'appel est toujours fait, et par conséquent, que la Proximité est toujours appelé, indépendamment de ce que les flux de contrôle se produit.
À mon avis, il est nécessaire d'envelopper toute classe qui implémente IDisposable dans un bloc using. Le fait qu'une classe implémente IDisposable signifie que la classe a des ressources qui ont besoin d'être nettoyé.
Ma règle d'or est, si je vois Disposer énumérés à l'intellisense, je l'envelopper dans un bloc using.
l'aide de bloquer les appels dispose() quand elle se termine. C'est juste un moyen pratique de s'assurer que les ressources sont nettoyées en temps opportun.
Dans presque tous les cas, si une classe implémente IDisposable, et si vous êtes en train de créer une instance de cette classe, alors vous avez besoin de l'aide du bloc.
Alors qu'il est de bonne pratique de toujours jetez jetables classes telles que StreamWriter, comme d'autres, dans ce cas, il n'a pas d'importance.
Réponse.OutputStream seront éliminés par le ASP.NET l'infrastructure lorsque c'est fini, le traitement de votre demande.
StreamWriter suppose qu'il "possède" un Flux de données transmis au constructeur, et donc de Fermer le flux de données quand il est éliminé. Mais dans l'exemple que vous fournissez, le flux a été instancié à l'extérieur de votre code, donc il y aura un autre propriétaire qui est responsable pour le nettoyage.