Does. Развертывание StreamWriter закрывает базовый поток?

StreamWriter.Close() говорит, что он также закрывает базовый поток StreamWriter. Что относительно StreamWriter.Dispose? Dispose также удаляет и/или закрывает базовый поток.

Ответ 1

StreamWriter.Close() просто вызывает StreamWriter.Dispose() под капотом, поэтому они делают то же самое. StreamWriter.Dispose() закрывает базовый поток.

Reflector является вашим другом для таких вопросов:)

Ответ 2

Некоторые люди скажут, просто не удаляйте поток, это действительно плохая идея, потому что, как только потоковик выходит из сферы видимости, GarbageCollection может в любой момент поднять его и рассеять, тем самым закрыв Handle для потока, но создав класс потомка, который переопределяет это поведение StreamWriter, легко, имеет код:

/// <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);
    }
}

Если вы посмотрите в Reflector/ILSpy, вы обнаружите, что закрытие базового потока фактически выполняется в Dispose (true), а когда вызывается close, оно просто вызывает Dispose, который вызывает Dispose (True), из кода, который должен не должно быть никаких других побочных эффектов, поэтому класс выше работает хорошо.

Возможно, вы захотите добавить все конструкторы, но я просто добавил 2 здесь для простоты.

Ответ 3

Из StreamWriter.Close()

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

Из TextWriter.Dispose() (который наследует StreamWriter)

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

Таким образом, они идентичны.

Ответ 4

Close и Dispose являются синонимами для StreamWriter.

Ответ 5

Чтобы привести цитаты из Руководства по дизайну каркасов от Cwalina и Abrams в разделе о шаблоне dispose:

CONSIDER, предоставляющий метод Close(), в дополнение к Dispose(), если close - стандартная терминология в области.

Очевидно, Microsoft придерживается своих собственных принципов и полагает, что это почти всегда безопасная ставка для библиотеки базового класса .NET.

Ответ 6

Ответ прост и приведен выше: да, удаление потока закрывает любой основной поток. Вот пример:

    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;
    }

и вот решение, где вам нужно отложить Dispose, где базовый MemoryStream больше не нужен:

    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;
    }

Глядя на эти примеры, я не понимаю, почему закрытие базового потока - это особенность.

Мне просто нравится делиться этим.