.net Stream.Dispose是否始终调用Stream.Close(和Stream.Flush)

mfpqipee  于 2023-01-18  发布在  .NET
关注(0)|答案(8)|浏览(131)

如果我有以下情况:

StreamWriter MySW = null;
try
{
   Stream MyStream = new FileStream("asdf.txt");
   MySW = new StreamWriter(MyStream);
   MySW.Write("blah");
}
finally
{
   if (MySW != null)
   {
      MySW.Flush();
      MySW.Close();
      MySW.Dispose();
   }
}

我可以直接调用MySW.Dispose()并跳过Close吗?是否有任何Stream实现不能按预期工作(如CryptoStream)?
如果不是,那么下面的代码就是错误的代码:

using (StreamWriter MySW = new StreamWriter(MyStream))
{
   MySW.Write("Blah");
}
j5fpnvbx

j5fpnvbx1#

我可以只调用MySW.Dispose()并跳过Close(即使提供了它)吗?
是的,这就是它的用途。
是否有任何Stream实现无法按预期工作(如CryptoStream)?
可以安全地假设,如果对象实现了IDisposable,它将正确地释放自身。
如果没有,那就是一个错误。
如果不是,那么下面的代码就是错误的代码:
不,该代码是处理实现IDisposable的对象的推荐方式。
更多优秀的信息在Close and Dispose - which to call?的公认答案中

km0tfn4u

km0tfn4u2#

我使用Reflector,发现System.IO.Stream.Dispose看起来像这样:

public void Dispose()
{
    this.Close();
}
piv4azn7

piv4azn73#

正如丹尼尔Bruckner提到的,Dispose()Close()实际上是相同的东西。
但是Stream在被释放/关闭时调用Flush()FileStream(我假设任何其他具有缓存机制的Stream)在被释放时调用Flush()
如果您正在扩展StreamMemoryStream等,则需要在释放/关闭时实现对Flush()的调用(如果必要)。

laawzig2

laawzig24#

所有标准的流(FileStream,CryptoStream)在关闭/释放时都会尝试刷新。我认为你可以在任何微软流实现中依赖这一点。
因此,如果刷新失败,Close/Dispose可能引发异常。
事实上,IIRC在FileStream的.NET 1.0实现中有一个bug,即如果刷新抛出异常,则无法释放文件句柄。在.NET 1.1中,通过向Dispose(布尔值)方法添加try/finally块修复了这个bug。

beq87vna

beq87vna5#

StreamWriter.Dispose()和Stream.Dispose()都会释放对象所拥有的所有资源。它们都会关闭底层流。
Stream.Dispose()的源代码(请注意,这是实现细节,所以不要依赖它):

public void Dispose()
{
    this.Close();
}

StreamWriter.Dispose()(与Stream.Dispose()相同):

protected override void Dispose(bool disposing)
{
    try
    {
        // Not relevant things
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {
            try
            {
                if (disposing)
                {
                    this.stream.Close();
                }
            }
            finally
            {
                // Not relevant things
            }
        }
    }
}

尽管如此,我通常在处理流/流编写器之前隐式地关闭它们-我认为这样看起来更干净。

p4rjhz4m

p4rjhz4m6#

对于需要手动关闭的对象,应尽一切努力在using块中创建对象。

//Cannot access 'stream'
using (FileStream stream = File.Open ("c:\\test.bin"))
{
   //Do work on 'stream'
} // 'stream' is closed and disposed of even if there is an exception escaping this block
// Cannot access 'stream'

通过这种方式,用户永远不会在using子句的上下文之外错误地访问“stream”,并且该文件总是关闭的。

smdnsysy

smdnsysy7#

我在.net源代码中查找了Stream类,它有以下内容,这表明是的,你可以...

// Stream used to require that all cleanup logic went into Close(),
    // which was thought up before we invented IDisposable.  However, we 
    // need to follow the IDisposable pattern so that users can write
    // sensible subclasses without needing to inspect all their base
    // classes, and without worrying about version brittleness, from a
    // base class switching to the Dispose pattern.  We're moving 
    // Stream to the Dispose(bool) pattern - that's where all subclasses
    // should put their cleanup starting in V2. 
    public virtual void Close() 
    {
        Dispose(true); 
        GC.SuppressFinalize(this);
    }

    public void Dispose() 
    {
        Close(); 
    }
ogq8wdun

ogq8wdun8#

Stream.Close是通过调用Stream.Dispose实现的,反之亦然-因此方法是等效的。Stream.Close存在的原因是关闭流听起来比释放流更自然。
此外,您应该尽量避免显式调用此方法,而是使用using语句,以便免费获得正确的异常处理。

相关问题