【问题标题】:C# Implementing Dispose - why need check disposing and disposed?C# 实现 Dispose - 为什么需要检查 Dispose 和 Dispose?
【发布时间】:2016-06-25 00:41:06
【问题描述】:

我搜索并没有找到确切的答案。我正在学习Implementing Dispose 的正确方法。我想知道为什么需要 2 个布尔值。

  1. 为什么需要处理?只有析构函数调用 Dispose (false),为什么析构函数不强制释放托管资源?
  2. 为什么需要处置?如果这个对象已经被释放了,怎么调用 Dispose 方法呢?你能告诉一个场景,当 Dispose 被调用并且被处理为 true 时?

【问题讨论】:

  • @Shazi 谢谢,我会详细阅读。
  • 如果 disposing 参数为 false,则该对象未被释放。它是运行的终结器(又名析构函数)。这很重要,这意味着您不能处理存储在字段中的任何对象,它们可能已经完成。您需要 disposed 以确保安全,客户端代码可能会多次调用 Dispose。编写自己的终结器并实现一次性模式有一个非常理想的特性,99.9% 的时间都是错误的。框架类需要这样做,而不是你。

标签: c# .net memory-management idisposable


【解决方案1】:

对于第二个问题:Dispose() 方法应该可以毫无问题地调用两次(参见IDisposable.Dispose()

如果对象的 Dispose 方法被多次调用,则该对象必须忽略第一次之后的所有调用。如果多次调用其 Dispose 方法,则该对象不得抛出异常。除 Dispose 之外的实例方法可以抛出 ObjectDisposedException当资源已经被释放时。

一个常见的情况是Stream 对象被传递给另一个拥有“所有权”的Stream 对象:

using (var ms = new MemoryStream())
{
    using (var sw = new StreamWriter(ms))
    //using (var sw = new StreamWriter(zip, Encoding.UTF8, 4096, true))
    {

    }

    // false: ms has already been disposed
    bool canWrite = ms.CanWrite;
}

StreamWriter 通常拥有底层流的所有权(在本例中为 ms),因此当调用 StreamWriterDispose() 时,MemoryStreamDispose() 也会被调用。 . 但是请注意,即使MemoryStream 也在using 块中,所以它的Dispose() 将被再次调用。

这里没有问题,因为各种Stream类的Dispose()都正确实现了。如果你想避免这种双重Dispose(),几乎所有Stream 类都有一个重载,告诉它们是否必须拥有底层Stream 的所有权(请参阅注释行...该参数称为leaveOpen ,因此通过将其设置为 true StreamWriter 不会 Dispose() 底层流)

【讨论】:

    【解决方案2】:

    disposing 布尔值用于指示从何处调用 Dispose。它是通过YourObject.Disposeusing 语句显式调用的,还是从终结器线程隐式调用的。

    这种区分是必要的,因为当 Dispose 从终结器线程运行时,无法保证任何托管对象在 object 中仍然存在,因此将 dispose 仅​​限于该类型拥有的非托管资源。

    disposed 布尔值用于标记对象已被释放。比如说,一个确实释放了对象,但实现缺少GC.SuppressFinalize(this)。即使对象已被释放,它仍会在其终结器执行后(再次)运行,并尝试再次释放那些已被释放的非托管资源。

    您提供的文档中的示例很好地解释了这一点:

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Free other state (managed objects).
            }
    
            // Free your own state (unmanaged objects).
            // Set large fields to null.
            disposed = true;
        }
    }
    

    【讨论】:

    • disposed怎么样,你好像还没提。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多