65

如果我有以下情况:

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()即使提供了关闭,我也可以直接调用并跳过关闭吗?是否有任何不能按预期工作的流实现(如 CryptoStream)?

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

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

8 回答 8

83

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

是的,这就是它的用途。

是否有任何未按预期工作的 Stream 实现(如 CryptoStream)?

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

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

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

不,该代码是处理实现IDisposable.

更优秀的信息在Close and Dispose 的公认答案中 - 调用哪个?

于 2009-05-26T15:55:49.637 回答
59

我使用了反射器,发现它System.IO.Stream.Dispose看起来像这样:

public void Dispose()
{
    this.Close();
}
于 2009-05-26T15:57:26.983 回答
22

正如 Daniel Bruckner 所说,Dispose 和 Close 实际上是一回事。

但是 Stream 在处理/关闭时不会调用 Flush() 。FileStream (我假设任何其他具有缓存机制的 Stream )在处置时确实调用了 Flush() 。

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

于 2009-06-18T23:52:19.773 回答
4

所有标准流(FileStream、CryptoStream)都将在关闭/处置时尝试刷新。我认为您可以将其用于任何 Microsoft 流实现。

因此,如果刷新失败,Close/Dispose 可能会引发异常。

事实上,IIRC 在 FileStream 的 .NET 1.0 实现中存在一个错误,即如果刷新引发异常,它将无法释放文件句柄。这在 .NET 1.1 中已通过向 Dispose(boolean) 方法添加 try/finally 块来解决。

于 2009-05-26T16:36:12.647 回答
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 - 我认为它看起来更干净。

于 2009-05-26T16:00:29.877 回答
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 子句的上下文之外错误地访问“流”,并且文件总是关闭的。

于 2009-06-19T00:54:02.753 回答
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(); 
    } 
于 2012-02-15T22:04:16.893 回答
2

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

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

于 2009-05-26T15:58:06.840 回答