我该如何确保处理可能的一次性物品?

时间:2009-12-29 17:31:28

标签: c# .net interface idisposable

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

如果我事先不知道工作是否需要明确处理,我应该如何确保所有工作在使用后妥善处理?我自己有一些想法,但是想听听你的意见/建议:

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

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

  3. 写完这篇文章之后,我倾向于倾向于解决方案#1,但我仍然认为看到替代解决方案会更好,并且我已经考虑过这两种方案的其他优点/缺点。

4 个答案:

答案 0 :(得分:8)

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

所以你的选择是:你想要所有的工作都是IDisposable还是只有一些?

第一个选项会产生很小的开销,第二个选项会在必要时更容易忘记Dispose(using)。

答案 1 :(得分:5)

#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();
        }
    }
}

答案 2 :(得分:3)

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

答案 3 :(得分:2)

我会选择#2并记录任何一次性物品将被丢弃。基本上,如果您取得对象的所有权,则您有义务处置实现IDisposable的对象。

如果您阅读了有效的C#/更有效的C#,Bill Wagner给出了同样的建议(我明白同意; - )