【问题标题】:Why is it preferred to not use finalize for clean up? .NET为什么首选不使用 finalize 进行清理? 。网
【发布时间】:2013-10-09 20:17:13
【问题描述】:

(Windows API 创建的对象、文件、数据库连接对象、COM 对象等)不在 .NET Framework 的范围内。我们必须明确地清理我们的资源。对于这些类型的对象,.NET Framework 提供了Object.Finalize 方法,可以重写和清理非托管资源的代码...

  1. 为什么首选不使用 finalize 进行清理?

  2. 用什么合适?

【问题讨论】:

    标签: .net finalize


    【解决方案1】:

    首选方法是实现IDisposabledispose pattern。终结器是有时间限制的,如果它阻塞太久,GC 将终止终结器 - 这是尽可能避免它的主要原因。

    Dispose 只是一个方法调用,没有时间限制。对于调用者忘记调用Dispose(因为它没有被强制执行)作为释放资源的最后尝试的情况,dispose 模式可以选择使用终结器。如果调用了 dispose,该模式还会抑制终结器。

    我遇到的需要终结器的唯一有效用途是用于我为第三方应用程序编写的一系列加载项,这些加载项没有引发相关事件以正确管理对象生命周期。我使用终结器来确保我至少尝试过清理东西。除此之外,我从未直接依赖它。

    IDisposable 在 C# 中使用 using 关键字来处理。任何实现这个接口的东西都可以这样使用:

    using (var myDisposableItem = new MyDisposableItem())
    {
    } // Dispose will be called here for you.
    

    所以从调用的角度来看,这很简单。

    .NET Framework 中有多种类型实现了IDisposable,但没有什么可处理的。我总是建议他们表现得好像他们需要直接处置一样,因为公共合同规定他们有东西要处置,即使实施没有。不要针对实现细节进行编程。

    【讨论】:

    • 感谢您提供非常好的答案。我想知道,c++ RAII 和 IDISPOSABLE 有什么区别?
    • @RamizHassan RAII 作为一个概念无法与IDisposable 相提并论,但要回答如果您在using 语句中发生异常会发生什么的问题,@987654331 @ 方法会被调用,因为编译器会为它生成一个try-finally
    • C# using 语句的要点是在 IDisposable 代码周围有一个很好的 try finally 块。把这两件事放在一起,我们就有了 RAII??
    • 与 .NET 中不需要它的 IDisposable 的所有类相比,您的最后一句话(“不要对实现细节进行编程”)不会计算,因为派生类型以后可能需要它,以及由 IDisposable 对象继承的所有类,而父对象不是 IDisposable。 IDisposable 接口是一个实现细节。您需要调用using (existingObject as IDisposable) { ... } 来捕获派生实现为 IDisposable 的所有情况,但父级的文档(和实现)没有提及 IDisposable。
    • 我想说,如果派生类依赖于在基类的上下文中调用 dispose 意味着公共合同已被破坏。
    猜你喜欢
    • 2015-10-16
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 2013-11-21
    • 2019-10-02
    • 1970-01-01
    相关资源
    最近更新 更多