. Удаляет ли StreamWriter базовый поток?

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

7 ответов

Решение

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

Отражатель - твой друг для подобных вопросов:)

Некоторые люди скажут, просто не утилизируйте поток, это действительно плохая идея, потому что, когда потоковый писатель выходит из области видимости, GarbageCollection может забрать его в любое время и добавить его, таким образом закрывая дескриптор потока, но создавая класс-потомок, который переопределяет это поведение 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 здесь для простоты.

От StreamWriter.Close()

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

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

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

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

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

Чтобы процитировать цитаты из Руководства по проектированию рамок от Квалины и Абрамса в разделе о шаблоне утилизации:

РАССМОТРЕТЬ метод предоставления Close(), в добавок к Dispose(), если близко - стандартная терминология в области.

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

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

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

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

Я просто любил поделиться этим.

Метод Dispose StreamWriter также закрывает базовый поток. Вы можете проверить это в справочном источнике здесь. Одна вещь, которую вы можете сделать, это использовать другой конструктор, который явно указывает, следует ли закрыть или оставить поток открытым. Проверьте аргумент leaveOpen:

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

Если вы планируете оставить его открытым, то рекомендуется передать флаг, установленный в «true», но затем удалить сам модуль записи потока, чтобы он не сохранял ссылку на поток и потенциально мог удалять другие ресурсы (хотя не похоже, что есть какие-либо ресурсы, кроме потока).

Другие вопросы по тегам