193 votes

Devrais-je appeler Close () ou Dispose () pour les objets de flux?

Des Classes d' Stream, StreamReader, StreamWriter etc implémente IDispose 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 de 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 appel 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() des constructions, et appelez - Close() méthode:

Est-il bon?

136voto

Enigmativity Points 26345

Un saut rapide dans Reflector.NET montre que l' Close() méthode StreamWriter est:

public override void Close()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

Et StreamReader est:

public override void Close()
{
    this.Dispose(true);
}

L' Dispose(bool disposing) remplacer en StreamReader est:

protected override void Dispose(bool disposing)
{
    try
    {
        if ((this.Closable && disposing) && (this.stream != null))
        {
            this.stream.Close();
        }
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {
            this.stream = null;
            /* deleted for brevity */
            base.Dispose(disposing);
        }
    }
}

L' StreamWriter méthode est similaire.

Ainsi, la lecture du code, il est clair que que vous pouvez appeler en 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.

Il descend donc à savoir si ou non il est plus lisible d'utiliser Dispose(), Close() et/ou using ( ... ) { ... }.

Ma préférence personnelle est qu' 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?

Je pense donc qu'il est préférable de faire cela:

using (var stream = ...)
{
    /* code */

    stream.Close();
}

Il n'a pas d'influence sur le comportement du code, mais il ne l'aide lisibilité.

58voto

Darin Dimitrov Points 528142

Non, vous ne devriez pas appeler ces méthodes manuellement. À la fin du bloc using , la méthode Dispose est automatiquement appelée, ce qui permet de libérer les ressources non gérées (au moins pour les classes .NET BCL standard telles que les flux, les lecteurs / rédacteurs, ...). Donc, vous pouvez aussi écrire votre code comme ceci:

 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);
        }
    }
}
 

La méthode Close appelle Dispose.

19voto

Heinzi Points 66519

La documentation dit que ces deux méthodes sont équivalentes:

StreamReader.Fermer: Cette mise en œuvre de Fermer appelle la méthode dispose en passant la valeur true.

StreamWriter.Proche: Cette mise en œuvre de Fermer appelle la méthode dispose en passant la valeur true.

Flux de données.Fermer: Cette méthode appelle dispose, spécifiez true pour libérer toutes les ressources.

Donc, ces deux sont tout aussi valables:

/* Option 1 */
using (StreamWriter writer = new StreamWriter(filename)) { 
   // do something
} 

/* Option 2 */
StreamWriter writer = new StreamWriter(filename)
try {
    // do something
}
finally {
    writer.Close();
}

Personnellement, je m'en tiendrais à la première option, car il contient moins de "bruit".

7voto

supercat Points 25534

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é Proche. 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 de 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é.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X