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

发布于 2024-07-21 07:21:47 字数 540 浏览 5 评论 0原文

如果我遇到以下情况:

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

即使提供了 Close,我是否可以只调用 MySW.Dispose() 并跳过 Close? 是否有任何 Stream 实现无法按预期工作(例如 CryptoStream)?

如果没有,那么下面的代码就是错误的:

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

If I have the following situation:

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

Can I just call MySW.Dispose() and skip the Close even though it is provided? Are there any Stream implimentations that don't work as expected (Like CryptoStream)?

If not, then is the following just bad code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

人心善变 2024-07-28 07:21:48

我使用 Reflector 并发现 System.IO.Stream.Dispose 如下所示:

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

I used Reflector and found that System.IO.Stream.Dispose looks like this:

public void Dispose()
{
    this.Close();
}
撑一把青伞 2024-07-28 07:21:48

正如 Daniel Bruckner 提到的,Dispose()Close() 实际上是相同

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

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

As Daniel Bruckner mentioned, Dispose() and Close() are effectively the same thing.

However Stream does NOT call Flush() when it is disposed/closed. FileStream (and I assume any other Stream with a caching mechanism) does call Flush() when disposed.

If you are extending Stream, or MemoryStream etc. you will need to implement a call to Flush() when disposed/closed if it is necessary.

榆西 2024-07-28 07:21:48

所有标准流(FileStream、CryptoStream)在关闭/处置时都会尝试刷新。 我认为您可以依靠它来实现任何 Microsoft 流。

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

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

All standard Streams (FileStream, CryptoStream) will attempt to flush when closed/disposed. I think you can rely on this for any Microsoft stream implementations.

As a result, Close/Dispose can throw an exception if the flush fails.

In fact IIRC there was a bug in the .NET 1.0 implementation of FileStream in that it would fail to release the file handle if the flush throws an exception. This was fixed in .NET 1.1 by adding a try/finally block to the Dispose(boolean) method.

韵柒 2024-07-28 07:21:48

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

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

Both StreamWriter.Dispose() and Stream.Dispose() release all resources held by the objects. Both of them close the underlying stream.

The source code of Stream.Dispose() (note that this is implementation details so don't rely on it):

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

StreamWriter.Dispose() (same as with 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
            }
        }
    }
}

Still, I usually implicitly close streams/streamwriters before disposing them - I think it looks cleaner.

寻梦旅人 2024-07-28 07:21:48

对于需要手动关闭的对象,应尽一切努力在 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 子句的上下文之外错误地访问“流”,并且文件始终处于关闭状态。

For objects that need to be manually closed, every effort should be made to create the object in a using block.

//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' 

In this way one can never incorrectly access 'stream' out of the context of the using clause and the file is always closed.

浪荡不羁 2024-07-28 07:21:48

我查看了 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(); 
    } 

I looked in the .net source for the Stream class, it had the following which would suggest that yes you can...

    // 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(); 
    } 
半透明的墙 2024-07-28 07:21:48

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

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

Stream.Close is implemented by a call to Stream.Dispose or vice versa - so the methods are equivalent. Stream.Close exists just because closing a stream sounds more natural than disposing a stream.

Besides you should try to avoid explicit calls to this methods and use the using statement instead in order to get correct exception handling for free.

窝囊感情。 2024-07-28 07:21:47

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

是的,这就是它的用途。

是否有任何 Stream 实现
不能按预期工作(例如
加密流)?

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

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

如果不是,那么下面的内容就很糟糕
代码:

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

更多精彩信息请参见关闭和处置 - 调用哪个?

Can I just call MySW.Dispose() and
skip the Close even though it is
provided?

Yes, that’s what it’s for.

Are there any Stream implementations
that don't work as expected (Like
CryptoStream)?

It is safe to assume that if an object implements IDisposable, it will dispose of itself properly.

If it doesn’t, then that would be a bug.

If not, then is the following just bad
code:

No, that code is the recommended way of dealing with objects that implement IDisposable.

More excellent information is in the accepted answer to Close and Dispose - which to call?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文