I have a class that essentially wraps a Stream for reading/writing, but that stream is expected to be managed by the consumer of that class. For ease of use, I use StreamReader and StreamWriter classes to perform I/O operations on the stream. Normally I'd wrap the reader and writer in using
blocks, but I want to avoid closing the reader and writer because doing so also closes the underlying stream and I have to keep it open.
Is it safe in terms of memory/resource management to not close a StreamReader/StreamWriter if I expect the underlying Stream to be managed by the caller? Will the reader and writer be garbage collected when the stream is explicitly closed elsewhere?
public class Wrapper
{
private Stream _underlyingStream;
public Wrapper(Stream underlyingStream)
{
_underlyingStream = underlyingStream;
}
public string GetValue()
{
_underlyingStream.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(_underlyingStream);
return reader.ReadToEnd(); // we're done, but the stream is not ours to close
}
}
1 Answer. No, there is no need to explicitly call reader. Close if the reading process is inside a using block. By using a using statement (that sounds awkward out loud) everything will be closed and disposed when the code exits the block.
Yes, StreamReader , StreamWriter , BinaryReader and BinaryWriter all close/dispose their underlying streams when you call Dispose on them.
It does not dispose the stream. It simply closes it.
If nobody closes the streams then ultimately the finalizer will be called which should call dispose and close them upon GC. But that's quite a crap-shoot resource-wise because it leaves whatever possibly-expensive resources allocated until GC. It could get worse the longer your object lives, especially if it survives collections to be promoted to gen 1 or even 2.
It sure would be nice if you could present something to your caller that isolates this. Perhaps you can cache something from the stream so you can close it while still serving the content to your caller?
EDIT after your edit: Now that I see your caller PASSES you a stream to operate on, my answer has to be different! It's very clear that your caller should be managing the stream's lifetime. I had the impression at first that your class created a stream and hoped the caller managed it.
The easiest way to solve this is to wrap the stream in your own class that derives from System.IO.Stream
Example: http://csharptest.net/browse/src/Library/IO/NonClosingStream.cs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With