Stream.Dispose总是调用Stream.Close(和Stream.Flush)

时间:2009-05-26 15:51:31

标签: c# .net using

如果我有以下情况:

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()并跳过关闭,即使提供了吗?是否存在任何不能按预期工作的Stream implament(如CryptoStream)?

如果没有,那么以下只是错误的代码:

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

8 个答案:

答案 0 :(得分:80)

  

我可以调用MySW.Dispose()和   跳过关闭,即使它是   提供?

是的,这就是它的用途。

  

是否有任何Stream实现   不能按预期工作(喜欢   CryptoStream的)?

可以安全地假设,如果一个对象实现IDisposable,它将正确处理它。

如果没有,则那将是一个错误。

  

如果没有,那么以下就是坏事   代码:

不,该代码是处理实现IDisposable的对象的推荐方法。

Close and Dispose - which to call?

的接受答案中包含更多优秀信息

答案 1 :(得分:58)

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

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

答案 2 :(得分:21)

Daniel Bruckner提到,Dispose和Close实际上是一回事。

然而,Stream在处理/关闭时不会调用Flush()。 FileStream(我假设任何其他具有缓存机制的Stream)在处理时调用Flush()。

如果您正在扩展Stream或MemoryStream等,则需要在处理/关闭时执行对Flush()的调用。

答案 3 :(得分:3)

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

尽管如此,我通常会在处理它们之前隐式关闭流/ streamwriters - 我觉得它看起来更干净。

答案 4 :(得分:3)

所有标准Streams(FileStream,CryptoStream)将在关闭/处置时尝试刷新。我认为你可以依赖于任何Microsoft流实现。

因此,如果刷新失败,Close / Dispose会抛出异常。

事实上,IIRC在FileStream的.NET 1.0实现中存在一个错误,如果flush抛出异常,它将无法释放文件句柄。通过在Dispose(boolean)方法中添加try / finally块,可以在.NET 1.1中修复此问题。

答案 5 :(得分:3)

对于需要手动关闭的对象,应尽一切努力在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',并且文件总是被关闭。

答案 6 :(得分:3)

我查看了Stream类的.net源代码,它有以下内容表明你可以......

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

答案 7 :(得分:2)

Stream.Close是通过调用Stream.Dispose实现的,反之亦然 - 因此方法是等效的。 Stream.Close的存在只是因为关闭流听起来比处理流更自然。

此外,您应该尝试避免显式调用此方法并使用using语句,以便免费获得正确的异常处理。