Is it okay to not close StreamReader/StreamWriter

2019-04-18 11:30发布

问题:

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:

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.



回答2:

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



回答3:

It is definetelly not ok. read this from msdn

The close calls the Dispose method passing a true value. Flushing the stream will not flush its underlying encoder unless you explicitly call Close.

Try to encapsulate all IO in a class.



标签: c# stream