【问题标题】:Does .Disposing a StreamWriter close the underlying stream?.Disposing a StreamWriter 是否会关闭底层流?
【发布时间】:2010-11-14 08:01:18
【问题描述】:

StreamWriter.Close() 表示它还关闭了 StreamWriter 的底层流。 StreamWriter.Dispose 呢? Dispose 是否也释放和/或关闭底层流

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    StreamWriter.Close() 只是在引擎盖下调用 StreamWriter.Dispose(),所以它们做的事情完全相同。 StreamWriter.Dispose() 确实关闭了底层流。

    Reflector 是您的朋友,可以解答此类问题:)

    【讨论】:

    • 从技术上讲,它在引擎盖下调用 Dispose(bool),尽管这是一个最轻微的挑剔
    • 你是对的。我应该说它“调用 dispose”而没有实际指定哪个重载。好地方。
    • 处理流。它只是关闭它。
    • @cloggins - 这就是我所说的:“StreamWriter.Dispose() 确实关闭了底层流”。我从来没有说过它会处理底层流。
    • Stream.Close() 调用 Stream.Dispose(true),因此除非在实现类中重写此行为,否则它相当于同一件事。
    【解决方案2】:

    有些人会说,不要dispose流,这是一个非常糟糕的主意,因为一旦streamwriter超出范围GarbageCollection可以随时拾取并dipose,从而关闭流的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(True) 的 Dispose,从代码中应该没有其他副作用,所以上面的类工作得很好。

    不过,您可能想添加所有构造函数,为了简单起见,我只是在此处添加了 2 个。

    【讨论】:

    • 您正在尝试解决一个不存在的问题。 GC 不会 处理任何对象,它会finalize 它们。而StreamWriter 的终结器调用Dispose(false),即不会处置BaseStream。我说,因为StreamWriter 甚至没有终结器——因为它不需要终结器(它的终结器没有任何意义)。
    【解决方案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 在关于处置模式的部分中的 Framework Design Guidelines

        考虑提供方法Close(),除了Dispose(),如果关闭是该领域的标准术语。

        显然微软遵循他们自己的指导方针,并假设这对于 .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;
              }
          

          看了这些例子,我不明白为什么关闭底层流是一个特性。

          我只是喜欢分享这个。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-11-28
            • 2011-05-26
            • 2015-09-19
            • 2023-03-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多