Lo streamreader di smaltimento chiude lo stream?

Sto inviando un stream ai metodi su cui scrivere, e in quei metodi sto usando un lettore / writter binario. Quando il lettore / scrittore viene eliminato, sia using o solo quando non è referenziato, lo stream è chiuso pure?

Vorrei inviare un BinaryReader / Writer, ma sto usando anche uno StreamReader (forse dovrei andare in giro, lo sto usando solo per GetLine e ReadLine). Questo è abbastanza fastidioso se chiude il stream ogni volta che uno scrittore / lettore viene chiuso.

Sì, StreamReader , StreamWriter , BinaryReader e BinaryWriter chiudono / BinaryReader loro flussi sottostanti quando si chiama Dispose su di essi. Non smaltiscono il stream se il lettore / scrittore è solo spazzatura ma – dovresti sempre disporre del lettore / scrittore, preferibilmente con una dichiarazione using . (In effetti, nessuna di queste classi ha finalizzatori, né dovrebbe avere.)

Personalmente preferisco avere un’istruzione using per lo stream. È ansible nidificare using istruzioni senza parentesi in modo abbastanza preciso:

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

Anche se l’istruzione using per lo stream è alquanto ridondante (a meno che il costruttore StreamReader non StreamReader un’eccezione), ritengo che sia la migliore pratica in quel caso, se ti sbarazzi di StreamReader e usi lo stream direttamente in un secondo momento, avrai già la giusta semantica per lo smaltimento.

Questo è vecchio, ma volevo fare qualcosa di simile oggi e ho scoperto che le cose sono cambiate. Da .net 4.5, c’è un argomento leaveOpen :

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

L’unico problema è che non è del tutto ovvio cosa impostare per gli altri parametri. Ecco un aiuto:

Dalla pagina msdn per StreamReader Constructor (Stream):

Questo costruttore inizializza la codifica in UTF8Encoding, la proprietà BaseStream utilizzando il parametro stream e la dimensione del buffer interno a 1024 byte.

Quello lascia appena detectEncodingFromByteOrderMarks che giudicare dal codice sorgente è true

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

Sarebbe bello se alcuni di questi valori di default fossero esposti o se gli argomenti fossero opzionali in modo da poter specificare solo quelli che vogliamo.

Sì, lo fa. Puoi verificarlo osservando l’implementazione 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); } } } 

Sei anni di ritardo ma forse questo potrebbe aiutare qualcuno.

StreamReader chiude la connessione quando viene eliminata. Tuttavia, “usando (Stream stream = …) {…}” con StreamReader / StreamWriter può comportare che il stream venga eliminato due volte: (1) quando l’object StreamReader è disposto (2) e quando il stream utilizza il blocco chiude. Ciò si traduce in un avviso CA2202 durante l’esecuzione dell’analisi del codice di VS.

Un’altra soluzione, presa direttamente dalla pagina CA2202 , consiste nell’utilizzare un blocco try / finally. Configura correttamente, questo chiuderà la connessione solo una volta.

Vicino alla parte inferiore di CA2202 , Microsoft consiglia di utilizzare quanto segue:

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

invece di…

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

Sì. Chiamando Dispose () on e IDisposable (cosa che “using” fa) dovrebbe fare in modo che un object ripulisca tutte le sue risorse. Ciò include flussi che scaricano e chiudono i descrittori di file.

Se, nel tuo caso, vuoi passarlo ad altri metodi, allora devi assicurarti che quei metodi non facciano la loro lettura / scrittura in un blocco usando.

Un modo semplice per risolvere questo problema, se necessario, è sovrascrivere il metodo Dispose delle classi StreamWriter. Vedi il mio post qui per il codice su come farlo:

.Disposing di uno StreamWriter chiude lo stream sottostante?

lo stream disposto da “utilizzare” la parola chiave o chiamare dispose in modo esplicito