C#实施处置-为什么需要检查处置和处置?

C#实施处置-为什么需要检查处置和处置?,c#,.net,memory-management,idisposable,C#,.net,Memory Management,Idisposable,我搜索了一下,没有找到确切的答案。我正在学习正确的学习方法。我想知道为什么需要这两个布尔 为什么需要处理?只有析构函数调用Dispose(false),那么为什么析构函数不强制释放托管资源呢 为什么需要处置?如果此对象已被释放,如何调用Dispose方法?您能告诉我们一个场景,何时调用Dispose并且disposed为true吗 Dispose布尔值用于指示调用Dispose的位置。它是通过YourObject.Dispose或使用语句的显式调用的,还是从终结器线程隐式调用的 之所以需要这种区

我搜索了一下,没有找到确切的答案。我正在学习正确的学习方法。我想知道为什么需要这两个布尔

  • 为什么需要处理?只有析构函数调用Dispose(false),那么为什么析构函数不强制释放托管资源呢
  • 为什么需要处置?如果此对象已被释放,如何调用Dispose方法?您能告诉我们一个场景,何时调用Dispose并且disposed为true吗

  • Dispose
    布尔值用于指示调用
    Dispose
    的位置。它是通过
    YourObject.Dispose
    或使用
    语句的
    显式调用的,还是从终结器线程隐式调用的

    之所以需要这种区别,是因为当从终结器线程运行
    Dispose
    时,无法保证对象中的任何托管对象仍然处于活动状态,因此仅将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;
        }
    }
    

    对于第二个问题:
    Dispose()
    方法应该可以调用两次而不会出现问题(请参阅:

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

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

    StreamWriter
    通常拥有底层流的所有权(在本例中为
    ms
    ),因此当调用
    StreamWriter
    Dispose()
    时,
    Dispose()也被调用
    内存流的
    …但请注意,即使是
    内存流
    也位于
    using
    块中,因此其
    Dispose()
    将再次调用


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

    您签出了吗?@Shazi谢谢,我会详细阅读它。如果disposing参数为false,则对象不会被处置。它是终结器(又名析构函数)这很重要,这意味着您无法处置存储在字段中的任何对象,它们可能已经被终结。为了安全起见,您需要处置,客户端代码可能会多次调用dispose。编写自己的终结器并实现一次性模式有一个非常可取的特点,99.9%的时间是错误的。Framework班级需要这样做,而不是你。怎么样,似乎你还没有提到。
    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;
    }