Ha Stream.Dispose chiamare sempre Stream.Close (e Stream.Flush)
Domanda
Se ho la seguente situazione:
StreamWriter MySW = null;
try
{
Stream MyStream = new FileStream("asdf.txt");
MySW = new StreamWriter(MyStream);
MySW.Write("blah");
}
finally
{
if (MySW != null)
{
MySW.Flush();
MySW.Close();
MySW.Dispose();
}
}
Posso chiamare MySW.Dispose()
e saltare il primo, anche se è previsto? Ci sono implimentations Ruscello che non funzionano come previsto (come CryptoStream)?
In caso contrario, è il seguente codice solo male:
using (StreamWriter MySW = new StreamWriter(MyStream))
{
MySW.Write("Blah");
}
Soluzione
Posso chiamare MySW.Dispose () e saltare il primo anche se è a condizione?
Sì, questo è quello che è per.
Ci sono implementazioni Ruscello che non funzionano come previsto (come CryptoStream)?
È lecito ritenere che se un oggetto implementa IDisposable
, esso cederà stessa correttamente.
Se non lo fa, allora sarebbe un bug.
In caso contrario, è la seguente solo male codice:
No, che il codice è il metodo consigliato di trattare con gli oggetti che implementano IDisposable
.
Per informazioni più eccellente è nella risposta accettato di Chiudere e Dispose - che chiamare?
Altri suggerimenti
Ho usato Reflector e ha scoperto che System.IO.Stream.Dispose
assomiglia a questo:
public void Dispose()
{
this.Close();
}
Come detto Daniel Bruckner, di disporne e chiudere sono di fatto la stessa cosa.
Tuttavia stream non chiama filo () quando è disposto / chiuso. FileStream (e presumo qualsiasi altro flusso con un meccanismo di cache) fa chiamata filo () quando disposto.
Se si estende Stream o MemoryStream ecc dovrai implementare una chiamata a flush () quando disposto / chiuso se è necessario.
Sia StreamWriter.Dispose () e Stream.Dispose () rilasciare tutte le risorse possedute dagli oggetti. Entrambi chiudere il flusso sottostante.
Il codice sorgente di Stream.Dispose () (notare che questo è i dettagli di implementazione in modo da non si basano su di esso):
public void Dispose()
{
this.Close();
}
StreamWriter.Dispose () (stesso con Stream.Dispose ()):
protected override void Dispose(bool disposing)
{
try
{
// Not relevant things
}
finally
{
if (this.Closable && (this.stream != null))
{
try
{
if (disposing)
{
this.stream.Close();
}
}
finally
{
// Not relevant things
}
}
}
}
Ancora, io di solito implicitamente torrenti stretti / streamwriters prima di smaltimento - penso che sembra più pulito
.Tutti i flussi standard (FileStream, CryptoStream) cercheranno di irrigare quando chiuso / disposta. Penso che si possa fare affidamento su questo per eventuali implementazioni flusso di Microsoft.
Come risultato, chiudere / smaltimento può generare un'eccezione se il colore non riesce.
In realtà IIRC c'era un bug nell'implementazione .NET 1.0 di FileStream in quanto non riuscirebbe a liberare l'handle di file se il filo genera un'eccezione. Questo è stato risolto in .NET 1.1 con l'aggiunta di un blocco try / finally al metodo Dispose (Boolean).
Per gli oggetti che devono essere chiusi manualmente, ogni sforzo dovrebbe essere fatto per creare l'oggetto in un blocco utilizzando.
//Cannot access 'stream'
using (FileStream stream = File.Open ("c:\\test.bin"))
{
//Do work on 'stream'
} // 'stream' is closed and disposed of even if there is an exception escaping this block
// Cannot access 'stream'
In questo modo non si può mai accedere in modo non corretto 'flusso' fuori dal contesto della clausola di utilizzo e il file è sempre chiuso.
Ho guardato nel codice .NET per la classe Stream, aveva il seguente che suggerirebbe che sì è possibile ...
// Stream used to require that all cleanup logic went into Close(),
// which was thought up before we invented IDisposable. However, we
// need to follow the IDisposable pattern so that users can write
// sensible subclasses without needing to inspect all their base
// classes, and without worrying about version brittleness, from a
// base class switching to the Dispose pattern. We're moving
// Stream to the Dispose(bool) pattern - that's where all subclasses
// should put their cleanup starting in V2.
public virtual void Close()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose()
{
Close();
}
Stream.Close
è implementato da una chiamata a Stream.Dispose
o viceversa - così i metodi sono equivalenti. Stream.Close
esiste solo perché la chiusura di un flusso di suoni più naturale di smaltire un flusso.
Inoltre si dovrebbe cercare di evitare le chiamate esplicite a questo metodi e utilizzare l'istruzione using
invece al fine di ottenere corretta gestione delle eccezioni gratuitamente.