Does .Disposing a StreamWriter close the underlying stream?

C#.Net

C# Problem Overview


The StreamWriter.Close() says it also closes the underlying stream of the StreamWriter. What about StreamWriter.Dispose ? Does Dispose also dispose and/or close the underlying stream

C# Solutions


Solution 1 - C#

StreamWriter.Close() just calls StreamWriter.Dispose() under the bonnet, so they do exactly the same thing. StreamWriter.Dispose() does close the underlying stream.

Reflector is your friend for questions like this :)

Solution 2 - C#

Some people will say, just dont dispose the stream, this is a really bad idea, because once the streamwriter goes out of scope GarbageCollection can pick it up anytime and dipose it, thus closing the Handle to the stream, but creating a descendant class which overrides this behaviour of StreamWriter is easy, heres the code:

/// <summary>
/// Encapsulates a stream writer which does not close the underlying stream.
/// </summary>
public class NoCloseStreamWriter : StreamWriter
{
    /// <summary>
    /// Creates a new stream writer object.
    /// </summary>
    /// <param name="stream">The underlying stream to write to.</param>
    /// <param name="encoding">The encoding for the stream.</param>
    public NoCloseStreamWriter(Stream stream, Encoding encoding)
        : base(stream, encoding)
    {
    }

    /// <summary>
    /// Creates a new stream writer object using default encoding.
    /// </summary>
    /// <param name="stream">The underlying stream to write to.</param>
    /// <param name="encoding">The encoding for the stream.</param>
    public NoCloseStreamWriter(Stream stream)
        : base(stream)
    {
    }

    /// <summary>
    /// Disposes of the stream writer.
    /// </summary>
    /// <param name="disposing">True to dispose managed objects.</param>
    protected override void Dispose(bool disposeManaged)
    {
        // Dispose the stream writer but pass false to the dispose
        // method to stop it from closing the underlying stream
        base.Dispose(false);
    }
}

If you look in Reflector / ILSpy you will find that the closing of the base stream is actually done in Dispose(true), and when close is called it just calls Dispose which calls Dispose(True), from the code there should be no other side effects, so the class above works nicely.

You might want to add all the constructors though, i have just added 2 here for simplicity.

Solution 3 - C#

From StreamWriter.Close()

public override void Close()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

From TextWriter.Dispose() (which StreamWriter inherits)

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

They are thus, identical.

Solution 4 - C#

Close and Dispose are synonymous for StreamWriter.

Solution 5 - C#

To quote from Framework Design Guidelines by Cwalina and Abrams in the section about the dispose pattern:

> CONSIDER providing method Close(), in addition to the Dispose(), if close is standard terminology in the area.

Apparently Microsoft follow their own guidelines, and assuming this is almost always a safe bet for the .NET base class library.

Solution 6 - C#

The answer is simple, and provided above: yes, disposing a stream closes any underlying stream. Here is an example:

    public static string PrettyPrintXML_bug(XDocument document)
    {
        string Result = "";
        using (MemoryStream mStream = new MemoryStream())
        {
            using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode))
            {
                writer.Formatting = Formatting.Indented; // <<--- this does the trick
                // Write the XML into a formatting XmlTextWriter
                document.WriteTo(writer);
                // change the memory stream from write to read
                writer.Flush();
                mStream.Flush();
            } // <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- this also "closes" mStream
            mStream.Position = 0;//rewind    <-- <-- <-- "cannot Read/Write/Seek"
            // Read MemoryStream contents into a StreamReader.
            using (StreamReader sReader = new StreamReader(mStream)) //  <-- <-- Exception: Cannot access a closed stream
            {
                // Extract the text from the StreamReader.
                Result = sReader.ReadToEnd();
            }
        }
        return Result;
    }

and here the solution, where you have to delay Dispose to where the underlying MemoryStream is not needed anymore:

    public static string PrettyPrintXML(XDocument document)
    {
        string Result = "";
        using (MemoryStream mStream = new MemoryStream())
        {
            using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode))
            {
                writer.Formatting = Formatting.Indented; // <<--- this does the trick
                // Write the XML into a formatting XmlTextWriter
                document.WriteTo(writer);
                // change the memory stream from write to read
                writer.Flush();
                writer.Close();
                mStream.Flush();
                mStream.Position = 0;//rewind
                // Read MemoryStream contents into a StreamReader.
                using (StreamReader sReader = new StreamReader(mStream))
                {
                    // Extract the text from the StreamReader.
                    Result = sReader.ReadToEnd();
                }
            }// <-- here the writer may be Disposed
        }
        return Result;
    }

Looking at these examples, I do not understand why closing the underlying stream is a feature.

I just liked to share this.

Solution 7 - C#

The Dispose method of StreamWriter also closes the underlying stream. You can check this in the reference source here. One thing that you can do is to use a different constructor, which explicitly tells whether to close or keep the stream open. Check the leaveOpen arg:

public StreamWriter(Stream stream, Encoding encoding, int bufferSize, bool leaveOpen) : base(null)

If you plan to leave it open, then it's a good idea to pass the flag set to 'true', but then dispose the stream writer itself, so it doesn't keep a reference to the stream and potentially could dispose other resources (though it doesn't look like there are any resources besides the stream).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnosView Question on Stackoverflow
Solution 1 - C#Rob LevineView Answer on Stackoverflow
Solution 2 - C#Aaron MurgatroydView Answer on Stackoverflow
Solution 3 - C#ShuggyCoUkView Answer on Stackoverflow
Solution 4 - C#Joel CoehoornView Answer on Stackoverflow
Solution 5 - C#Martin LiversageView Answer on Stackoverflow
Solution 6 - C#RolandView Answer on Stackoverflow
Solution 7 - C#usernameView Answer on Stackoverflow