Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么';在.NET中重写Dispose(bool disposing)的目的是什么?_C#_.net_Dispose_Idisposable - Fatal编程技术网

C# 什么';在.NET中重写Dispose(bool disposing)的目的是什么?

C# 什么';在.NET中重写Dispose(bool disposing)的目的是什么?,c#,.net,dispose,idisposable,C#,.net,Dispose,Idisposable,如果我用C#编写一个实现IDisposable的类,为什么它不足以让我简单地实现 public void Dispose(){ ... } 释放任何非托管资源 是 总是必要的,有时是必要的,还是其他什么?布尔处理的附加方法来自某个框架设计指南。它只是一种模式,允许类多次调用dispose方法而不引发异常。这不是绝对需要的。从技术上讲,您可以使用dispose方法来执行此操作 严格来说这不是必要的。这是推荐的一次性模式的一部分。如果您还没有阅读框架设计指南部分(第一版中的9.3,第二版手边没有

如果我用C#编写一个实现IDisposable的类,为什么它不足以让我简单地实现

public void Dispose(){ ... } 
释放任何非托管资源


总是必要的,有时是必要的,还是其他什么?

布尔处理的附加方法来自某个框架设计指南。它只是一种模式,允许类多次调用dispose方法而不引发异常。这不是绝对需要的。从技术上讲,您可以使用dispose方法来执行此操作

严格来说这不是必要的。这是推荐的一次性模式的一部分。如果您还没有阅读框架设计指南部分(第一版中的9.3,第二版手边没有),那么您应该

区分一次性清理和可终结的垃圾收集很有用,但这会毁了我


你不必这样做,但你应该仔细阅读并理解为什么建议这样做,然后再将其视为不必要。

MSFT文档中有一点关于一次性模式的偏见。您应该实现IDisposable的原因有两个:

  • 您拥有实现IDisposable的类型的字段
  • 你有一个终结器
  • 案例1在大多数代码中都很常见。案例2在Microsoft编写的代码中非常常见,他们是围绕非托管资源编写托管包装的人,需要完成的人。但在代码中应该非常少见。毕竟,你有那么多好的.NET类来为你做这些肮脏的工作。您只需调用它们的Dispose()方法


    只有情况2需要一次性模式。微软需要经常使用它。大多数情况下,您只需要简单的Dispose()。

    包括终结器、引入新的虚拟方法和“密封”原始Dispose方法在内的完整模式非常通用,涵盖了所有基础

    除非在非托管资源上有直接句柄(应该是),否则不需要终结器

    如果你密封你的类(我关于密封类的观点现在可能已经广为人知了),那么引入虚拟方法就没有意义了

    我不记得上次我是什么时候以“复杂”的方式实现了
    IDisposable
    ,而不是以最明显的方式实现的,例如

    public void Dispose()
    {
        somethingElse.Dispose();
    }
    

    需要注意的一点是,如果您想要获得真正健壮的代码,那么应该确保在处理完之后不要尝试做任何事情,并在适当的地方抛出
    ObjectDisposedException
    。对于世界各地的开发人员都将使用的类库来说,这是一个很好的建议,但是如果这只是一个在您自己的工作区中使用的类,那么这将是一个非常多的工作,收获甚微。

    除了其他很好的答案之外,您可能还想查看以下文章:

    • (一次性设计原则)

    仅对其他人所说的内容进行扩展:不仅仅是因为您不需要“复杂的处置”,而是因为性能原因,您实际上不需要它

    如果您采用“复杂处置”路线,实现终结器,然后忘记显式处置对象,那么在真正处置对象之前,您的对象(以及它引用的任何对象)将经历额外的GC生成(因为CLR必须再次挂起以调用终结器)。这只会导致更多您不需要的内存压力。此外,在整个对象堆上调用终结器的成本非常高

    所以要避免,除非您(或您的派生类型)有非托管资源


    哦,当我们在这个领域的时候:你的类上处理来自其他类的事件的方法必须是“安全的”,以防在你的类被释放后被调用。最简单的方法是,如果该类被释放,只执行一个no-op。请参见

    它提供给您的一个功能是在Dispose()中执行与终结无关的工作,并且仍然可以清理非托管资源

    在终结器中对托管对象执行除“您自己”之外的任何操作都是非常。。。不可预知的这主要是由于您的终结器将在AppDomain的第2阶段关闭时以非确定性的方式被调用,因此当您的终结器被调用时,您仍然有引用的对象极有可能已经被终结

    将Dispose和finalizer调用分派到同一个方法允许您共享关闭代码,而布尔参数允许您跳过托管清理(如果有)


    此外,该方法的虚拟性为继承者添加自己的清理代码提供了一种简单的方法,从而减少了无意中不调用您的代码的风险。

    如果类实现了
    IDisposable.Dispose()
    ,并且派生类需要添加额外的逻辑,该类必须公开派生类可以链接到的某种
    Dispose
    方法。由于某些类可能实现
    IDisposable.Dispose()
    而没有公共的
    Dispose()
    方法,因此在
    IDisposable
    的所有实现中,拥有一个受
    保护的
    虚拟方法非常有用,无论它们是否有公共的
    Dispose
    方法。在大多数情况下,
    bool
    参数不是真正有意义的参数,但应将其视为伪参数,以使受保护的虚拟处置(bool)
    与可能是或可能不是公共的
    Dispose()
    具有不同的签名

    不使用
    受保护的虚拟处置(bool)
    的类将需要派生类以不同于约定的方式处理其清理逻辑。一些语言,如C++/CLI,仅用于扩展
    IDisposable
    实现
    public void Dispose()
    {
        somethingElse.Dispose();
    }