2009-07-27 9 views

Respuesta

42

StreamWriter.Close() sólo llama StreamWriter.Dispose() bajo el capó, por lo que hacen exactamente lo mismo. StreamWriter.Dispose() cierra la secuencia subyacente.

Reflector es su amigo para este tipo de preguntas :)

+1

técnicamente llama a Dispose (bool) debajo del capó, un detalle más insignificante aunque – ShuggyCoUk

+1

tienes razón. Debería haber dicho que "pide deshacerse" sin especificar realmente qué sobrecarga. Buen lugar. –

+1

* No * elimina la transmisión. Simplemente lo cierra. – cloggins

6

Cerrar y botar son sinónimos de StreamWriter.

+0

Bueno, casi sinónimos. –

11

De StreamWriter.Close()

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

De TextWriter.Dispose() (que hereda StreamWriter)

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

Ellos son por lo tanto, idénticos.

2

citar marco Directrices de diseño por Cwalina y Abrams en la sección sobre el patrón disponer:

CONSIDERAN proporcionar método Close(), además de la Dispose(), si estrecha es la terminología estándar en el zona.

Aparentemente, Microsoft sigue sus propias pautas, y suponiendo que esto es casi siempre una apuesta segura para la biblioteca de clase base .NET.

14

Algunas personas dirán, apenas no deseche la corriente, esto es realmente una mala idea, porque una vez que el StreamWriter sale del ámbito GarbageCollection puede recogerlo en cualquier momento y dipose ella, cerrando así la manija a la corriente, pero la creación de una clase descendiente que anula este comportamiento de StreamWriter es fácil, aquí está el código:

/// <summary> 
/// Encapsulates a stream writer which does not close the underlying stream. 
/// </summary> 
public class NoCloseStreamWriter : StreamWriter 
{ 
    /// <summary> 
    /// Creates a new stream writer object. 
    /// </summary> 
    /// <param name="stream">The underlying stream to write to.</param> 
    /// <param name="encoding">The encoding for the stream.</param> 
    public NoCloseStreamWriter(Stream stream, Encoding encoding) 
     : base(stream, encoding) 
    { 
    } 

    /// <summary> 
    /// Creates a new stream writer object using default encoding. 
    /// </summary> 
    /// <param name="stream">The underlying stream to write to.</param> 
    /// <param name="encoding">The encoding for the stream.</param> 
    public NoCloseStreamWriter(Stream stream) 
     : base(stream) 
    { 
    } 

    /// <summary> 
    /// Disposes of the stream writer. 
    /// </summary> 
    /// <param name="disposing">True to dispose managed objects.</param> 
    protected override void Dispose(bool disposeManaged) 
    { 
     // Dispose the stream writer but pass false to the dispose 
     // method to stop it from closing the underlying stream 
     base.Dispose(false); 
    } 
} 

Si nos fijamos en el reflector/ILSpy usted encontrará que el cierre del flujo base se hace realmente en Dispose (true), y cuando se llama close, solo llama a Dispose which calls Dispose (True), desde el código no debería haber otros efectos secundarios, por lo que la clase anterior funciona bien.

Es posible que desee añadir todos los constructores, sin embargo, yo sólo he añadido 2 aquí por simplicidad.

+0

Muy útil para CryptoStream – nergeia

+7

Está intentando solucionar un problema que no existe. El GC * no * eliminará ningún objeto, * los finalizará *. Y el finalizador de 'StreamWriter' * llamaría' Dispose (false) ', es decir, * not * eliminaría el' BaseStream'. Digo * would *, porque 'StreamWriter' ni siquiera tiene un finalizador, porque no necesita uno (no hay nada significativo que pueda hacer en su finalizador). –

1

La respuesta es sencilla, y siempre por encima de: sí, disponiendo una corriente cierra cualquier secuencia subyacente. He aquí un ejemplo:

public static string PrettyPrintXML_bug(XDocument document) 
    { 
     string Result = ""; 
     using (MemoryStream mStream = new MemoryStream()) 
     { 
      using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode)) 
      { 
       writer.Formatting = Formatting.Indented; // <<--- this does the trick 
       // Write the XML into a formatting XmlTextWriter 
       document.WriteTo(writer); 
       // change the memory stream from write to read 
       writer.Flush(); 
       mStream.Flush(); 
      } // <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- this also "closes" mStream 
      mStream.Position = 0;//rewind <-- <-- <-- "cannot Read/Write/Seek" 
      // Read MemoryStream contents into a StreamReader. 
      using (StreamReader sReader = new StreamReader(mStream)) // <-- <-- Exception: Cannot access a closed stream 
      { 
       // Extract the text from the StreamReader. 
       Result = sReader.ReadToEnd(); 
      } 
     } 
     return Result; 
    } 

y aquí la solución, donde hay que retrasar botar a donde el MemoryStream subyacente no se necesita más:

public static string PrettyPrintXML(XDocument document) 
    { 
     string Result = ""; 
     using (MemoryStream mStream = new MemoryStream()) 
     { 
      using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode)) 
      { 
       writer.Formatting = Formatting.Indented; // <<--- this does the trick 
       // Write the XML into a formatting XmlTextWriter 
       document.WriteTo(writer); 
       // change the memory stream from write to read 
       writer.Flush(); 
       writer.Close(); 
       mStream.Flush(); 
       mStream.Position = 0;//rewind 
       // Read MemoryStream contents into a StreamReader. 
       using (StreamReader sReader = new StreamReader(mStream)) 
       { 
        // Extract the text from the StreamReader. 
        Result = sReader.ReadToEnd(); 
       } 
      }// <-- here the writer may be Disposed 
     } 
     return Result; 
    } 

Teniendo en cuenta estos ejemplos, no entiendo por qué cerrar la secuencia subyacente es una característica.

acabo le gusta compartir esto.

Cuestiones relacionadas