¿La eliminación de streamreader cierra la secuencia?

Estoy enviando una secuencia a los métodos para escribir, y en esos métodos estoy usando un lector binario / wrtier. Cuando el lector / escritor se elimina, ya sea al using o simplemente cuando no se hace referencia, ¿se cierra también la transmisión?

Enviaría un BinaryReader / Writer, pero también estoy usando StreamReader (tal vez debería ir por ahí. Solo estoy usando eso para GetLine y ReadLine). Esto es bastante problemático si cierra la secuencia cada vez que se cierra un escritor / lector.

Sí, StreamReader , StreamWriter , BinaryReader y BinaryWriter cierran / BinaryWriter sus flujos subyacentes cuando llamas a Dispose en ellos. Sin embargo, no se deshace de la transmisión si el lector / escritor no es más que basura: siempre debe desechar el lector / escritor, preferiblemente con una statement de using . (De hecho, ninguna de estas clases tiene finalizadores, ni deberían tener).

Personalmente, prefiero tener una statement de uso para la transmisión también. Puedes anidar using sentencias sin llaves bastante bien:

 using (Stream stream = ...) using (StreamReader reader = new StreamReader(stream, Encoding.Whatever)) { } 

A pesar de que la instrucción de using de la secuencia es algo redundante (a menos que el constructor de StreamReader arroje una excepción) considero que es una buena práctica, entonces si se deshace de StreamReader y simplemente utiliza la transmisión directamente en una fecha posterior, ya tendrá la semántica de disposición correcta.

Esta es una pregunta anterior, pero hoy quería hacer algo similar y descubrí que las cosas han cambiado. Desde .net 4.5, hay un argumento leaveOpen :

 public StreamReader( Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen ) 

El único problema es que no es completamente obvio qué establecer para los demás parámetros. Aquí hay algo de ayuda:

Desde la página msdn para StreamReader Constructor (Stream):

Este constructor inicializa la encoding a UTF8Encoding, la propiedad BaseStream utilizando el parámetro de flujo y el tamaño del buffer interno a 1024 bytes.

Eso solo deja detectEncodingFromByteOrderMarks que a juzgar por el código fuente es true

 public StreamReader(Stream stream) : this(stream, true) { } public StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks) : this(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks, DefaultBufferSize) { } 

Sería bueno si algunos de esos valores predeterminados estuvieran expuestos o si los argumentos fueran opcionales, de modo que pudiéramos simplemente especificar los que queramos.

Sí, lo hace. Puede verificar esto mirando la implementación con Reflector.

 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; this.encoding = null; this.decoder = null; this.byteBuffer = null; this.charBuffer = null; this.charPos = 0; this.charLen = 0; base.Dispose(disposing); } } } 

Seis años tarde, pero tal vez esto podría ayudar a alguien.

StreamReader cierra la conexión cuando se elimina. Sin embargo, “el uso (Stream stream = …) {…}” con StreamReader / StreamWriter puede dar como resultado que el Stream se elimine dos veces: (1) cuando el objeto StreamReader se elimina (2) y cuando el Stream usa el bloque cierra Esto da como resultado una advertencia CA2202 cuando se ejecuta el análisis de código de VS.

Otra solución, tomada directamente de la página CA2202 , es usar un bloque try / finally. Configurar correctamente, esto solo cerrará la conexión una vez.

Cerca de la parte inferior de CA2202 , Microsoft recomienda utilizar lo siguiente:

 Stream stream = null; try { stream = new FileStream("file.txt", FileMode.OpenOrCreate); using (StreamWriter writer = new StreamWriter(stream)) { stream = null; // Use the writer object... } } finally { if(stream != null) stream.Dispose(); } 

en lugar de…

 // Generates a CA2202 warning using (Stream stream = new FileStream("file.txt", FileMode.Open)) using (XmlReader reader = new XmlReader (stream)) { // Use the reader object... } 

Sí. Llamar a Dispose () y IDisposable (lo que “usa”) debe hacer que un objeto limpie todos sus recursos. Esto incluye la descarga de flujos y el cierre de sus descriptores de archivos.

Si, en su caso, desea pasarlo a otros métodos, entonces necesita asegurarse de que esos métodos no hagan su lectura / escritura en un bloque de uso.

Una manera fácil de arreglar esto si lo necesita es anular el método Dispose de las clases de StreamWriter. Vea mi publicación aquí para obtener el código sobre cómo hacerlo:

¿.Disponiendo un StreamWriter cierra la secuencia subyacente?

la stream dispuesta ya sea “utilizando” palabra clave o llamando a disponer explícitamente