Estoy de acuerdo con su pregunta. El mayor problema con este efecto secundario intencional es cuando los desarrolladores no lo conocen y siguen ciegamente la "mejor práctica" de rodear un StreamReader con un using
. Pero puede causar algunos realmente difícil de rastrear errores cuando se encuentra en la propiedad de un objeto de larga vida, la mejor (peor?) Ejemplo que he visto es
using (var sr = new StreamReader(HttpContext.Current.Request.InputStream))
{
body = sr.ReadToEnd();
}
El desarrollador no tenía idea de la InputStream es ahora manguera para cualquier lugar futuro que espera que esté allí.
Obviamente, una vez que conozca las partes internas, debe evitar el using
y simplemente leer y restablecer la posición. Pero pensé que un principio central del diseño de API era evitar los efectos secundarios, especialmente no destruir los datos sobre los que está actuando. Nada inherente a una clase que supuestamente es un "lector" debe borrar los datos que lee cuando se hace "usar". La eliminación del lector debe liberar cualquier referencia a la secuencia, no borrar la secuencia en sí. Lo único que puedo pensar es que la elección tuvo que hacerse ya que el lector está alterando otro estado interno de la secuencia, como la posición del puntero de búsqueda, que ellos asumieron que si está envolviendo un uso alrededor de él intencionalmente va a estar hecho con todo. Por otro lado, al igual que en su ejemplo, si está creando un Stream, el flujo en sí estará en un using
, pero si está leyendo un Stream que se creó fuera de su método inmediato, es presuntuoso del código de borrar los datos
lo que hago y digo a nuestros desarrolladores para hacer en casos Stream que el código de lectura no crea explícitamente es ...
// save position before reading
long position = theStream.Position;
theStream.Seek(0, SeekOrigin.Begin);
// DO NOT put this StreamReader in a using, StreamReader.Dispose() clears the stream
StreamReader sr = new StreamReader(theStream);
string content = sr.ReadToEnd();
theStream.Seek(position, SeekOrigin.Begin);
(lo siento, añade esto como una respuesta, no cabrían en un comentario, me gustaría más discusión sobre esta decisión de diseño del framework)
Considere también usar System.IO.File.ReadAllText() en situaciones como estas. Es mas simple –
@Dave Markle: tienes razón. Lo he puesto como un pequeño ejemplo. En realidad, en el código real, las transmisiones que trato pueden ser muy grandes, por lo que el primer lector las lee línea por línea, luego, la transmisión se copia por byte a otra transmisión. –