这个IDisposable对我有什么用?

时间:2011-12-05 22:05:24

标签: c# refactoring idisposable coderush

我正在制作一个“学习计划”并使用Code Rush重构工具和我的学习。随着Code Rush的最新更新,它一直建议在我的程序中实现IDisposable。我知道MSDN对IDisposable的看法,我对它的作用有一个真正基本的了解,但因为我不知道实现它的所有含义我一直忽略了这个建议。今天我决定更多地了解它并同意推荐。

这是它添加到我的程序中的内容。

class Program : IDisposable
{
    static Service _proxy;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
            if (_proxy != null)
            {
                _proxy.Dispose();
                _proxy = null;
            }
    }

    ~Program()
    {
        Dispose(false);
    }

所以我的问题就是这个。这样做我需要做些什么来获得IDisposable的优势,还是我需要在代码中做一些事情才能使它工作?我在其上设置了一个断点并且从未通过调试器到达它,因此要么不需要它,要么我没有按照预期的方式使用它。有人可以说明这对我的影响或我应该如何使用它以便它确实为我做了些什么?

2 个答案:

答案 0 :(得分:10)

在这种情况下,CodeRush建议您实施IDisposable,因为您的类封装了IDisposable资源(它看到了_proxy,尽管这不是一件好事,因为它是静态的)。 Code Rush认为你正在使用的类型应该明确清理,但是你没有提供一种方法来通过你的班级来实现。

话虽如此,IDisposable很棘手 - 这就是生成的代码实际上并不是一个好的实现的一种情况(即使_proxy是一个实例变量)。在这种情况下,我建议不要使用析构函数。它会导致GC中的性能问题,而在这种情况下对安全性没有帮助,因为封装的资源应该处理忘记为您调用Dispose()的情况。有关详细信息,请参阅my series on IDisposable,尤其是encapsulating an IDisposable class

此外,鉴于上面的代码,此类不应实现IDisposable(除非有其他理由这样做),因为_proxy资源为{ {1}}。从一个实例中处置静态资源可能会导致问题,至少在一般情况下如此。 (在这种情况下,它显然没有问题,但它不是一个好的做法...)通常,静态变量的寿命与实例成员的寿命非常不同,因此自动处理它是不合适的。

答案 1 :(得分:0)

在一个正确编写的程序中,在任何给定的时间,对于可能具有有意义的IDisposable实现的每个对象,将有一些实体负责确保IDisposable.Dispose将在某个时间之间被调用该实例的最后“真实用途”及其最终放弃。通常,如果对象Foo将持有对实现IDisposable的对象的引用,则至少应该应用以下场景之一:

  1. 其他一些对象也会保存引用,至少只要Foo需要它,并且会负责调用Dispose,因此Foo应该让其他对象处理Dispose。
  2. 持有引用的对象将是使用IDisposable对象的最后一件事;如果Foo没有调用Dispose,那么别的什么都不会。在这种情况下,Foo必须确保在不再需要(Foo)并且在它被放弃之前调用其他对象的Dispose方法。处理这个问题最惯用的方法是让Foo实现IDisposable.Dispose,并让Dispose方法在它拥有最后一个有用引用的IDisposable对象上调用Dispose。

在某些情况下,类设计人员可能不知道其类是否将保留对IDisposable对象的最后一个有用引用。在某些情况下,可以通过让类构造函数指定传递给构造函数的IDisposable是“lent”还是“given”来解决此问题。其他情况可能需要使用引用计数包装器或其他复杂技术。