【问题标题】:How should I ensure disposal of possibly disposable objects?我应该如何确保处置可能的一次性物品?
【发布时间】:2009-12-29 17:31:28
【问题描述】:

我正在开发一个 .NET 项目,该项目需要与一些用户定义的类进行交互 - 称为“作业”。所有作业类都必须实现特定接口IJob,以便库使用它们。有时,作业类可能包含非托管资源,需要显式处置。

如果我事先不知道作业是否需要明确处置,我应该如何确保在使用后正确处置所有作业?我自己有一些想法,但想听听您的 cmets/建议:

  1. 制作IJob : IDisposable,强制所有作业实现Dispose() 方法。这将允许我处理 using 块中的作业,但由于大多数作业预计需要明确处置,这可能会给客户端开发人员增加不必要的混乱。

  2. try-finally 块中执行所有涉及作业的工作,并使用finally 确保在作业实现IDisposable 时调用Dispose()。这使得客户端更容易实现新的作业类 - 不必实现空的 Dispose() 方法 - 但它也隐藏了库知道并关心一次性作业的事实。

写完这篇文章后,我倾向于解决方案 #1,但我仍然认为看到替代解决方案以及我已经想到的两个解决方案的其他优点/缺点会很好。

【问题讨论】:

    标签: c# .net interface idisposable


    【解决方案1】:

    有一个先例:Stream 基类是 IDisposable nad,因此所有 Streams 后代都是。但是 MemoryStream 不需要 Disposing。
    但不要针对 try/finally,using() { } 块是更方便的简写。

    所以您的选择是:您希望所有作业都是 IDisposable 还是只是一些?

    第一个选项会产生少量开销,第二个选项更容易在必要时忘记 Dispose(使用)。

    【讨论】:

    • 好点。但是,大多数流都需要处理,我预计只有少数工作需要处理。
    • 我突然想到System.Web.IHttpModule 也要求其实现者提供Dispose() 方法,尽管只有少数模块(恕我直言)需要它。我想这为#1 提供了额外的优先级。
    • +1,此外,我认为为 Job 提供一种标准化的方法来清理它使用的内容是有意义的。通过使用IDisposable,您可以从框架支持中受益,而最终用户至少需要考虑在哪里放置适当的清理代码。
    • +1 第二个选项也有一个缺点,即很容易在适配器中“丢失” IDisposable。拥有适配器和查询接口并不能很好地混合。使事情更明确使维护更容易。
    【解决方案2】:

    #2 是foreach 构造的工作方式。这也是 Autofac 容器处理的工作原理。

    语义上的区别在于您是说作业本身一次性的,还是说实现可能是一次性的。

    从您的示例中可以清楚地看出,前者不正确,工作本质上不是一次性的。因此,我推荐#2,但使用扩展方法来集中try/finally

    public static void Execute(this IJob job)
    {
        try
        {
            job.Run();
        }
        finally
        {
            var disposableJob = job as IDisposable;
    
            if(disposableJob != null)
            {
                disposableJob.Dispose();
            }
        }
    }
    

    【讨论】:

    • +1,我喜欢你关于语义的论点,但我想我会选择第一个解决方案,原因在其他答案和问题本身中提到。
    【解决方案3】:

    我是这样想的。我宁愿开发者实现一个空的Dispose 方法,也不愿忘记实现一个必要的Dispose 方法。

    【讨论】:

      【解决方案4】:

      我会选择 #2 并记录任何一次性物品都将被处置。基本上,如果你拥有一个对象的所有权,你就有义务处置实现 IDisposable 的对象。

      如果您阅读 Effective C#/More Effective C#,Bill Wagner 会给出相同的建议(我显然同意 ;-)

      【讨论】:

      • OP 已经在两个选项中处理拥有的对象,所以我看不出这是选项#2 的参数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多