Cosa succede quando un metodo che prende in ingresso uno Stream termina la sua esecuzione? Lo stream deve rimanere aperto oppure essere chiuso? In alcuni casi, è corretto che esso venga chiuso: ad esempio, se lo stream in questione è un FileStream, in questo modo all'uscita del metodo si ha a disposizione un file correttamente salvato su disco. In altre situazioni, però, lo stream dovrebbe rimanere aperto, perché si vogliono fare alcune elaborazioni sui dati che sono stati riversati in esso; pensiamo al MemoryStream: dopo che il metodo vi ha copiato il suo output, si potrebbe voler accedere ad esso per recuperare l'array di byte corrispondente ed inviarlo, ad esempio, su una connessione TCP.
La seguente situazione, quindi, potrebbe essere fonte di problemi: si utilizza il metodo di una libreria di terze parti, di cui non si ha il codice sorgente, il quale prende in ingresso uno stream e lo chiude al termine della sua elaborazione, ma in realtà si avrebbe bisogno che rimanesse aperto. In un caso del genere, per aggirare il problema è possibile estendere il tipo contenente lo stream che si sta utilizzando, ridefinendo il suo metodo Close:
namespace System.IO
{
class ClosableMemoryStream : MemoryStream
{
private bool _closeable;
public bool Closeable
{
get { return _closeable; }
set { _closeable = value; }
}
public ClosableMemoryStream()
: base()
{
_closeable = true;
}
public override void Close()
{
if (_closeable)
base.Close();
}
public void ForceClose()
{
base.Close();
}
}
}
In questo esempio si tratta di un MemoryStream. La proprietà Closable specifica se lo stream deve essere chiuso quando si richiama il suo metodo Close. Per evitare che lo stream venga chiuso dal metodo della libreria, è sufficiente passare a quest'ultima un oggetto di tipo ClosableMemoryStream (anziché MemoryStream), dopo aver impostato la sua proprietà Closable su false: quando sarà richiamato il metodo Close, verrà eseguito il suo override, quindi lo stream in realtà rimarrà aperto. Dopo aver effettuato tutte le elaborazioni necessarie, per la chiusura vera e propria è necessario richiamare il metodo ForceClose.