6

我正在研究一个“学习计划”,并在我的学习中使用 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 的优势,还是我需要在代码中做一些事情才能使它工作?我在上面设置了一个断点,并且从未通过调试器到达它,所以要么不需要它,要么我没有按照预期的方式使用它。有人可以解释一下这对我有什么作用或我应该如何使用它以便它对我有用吗?

4

2 回答 2

10

在这种情况下,CodeRush建议您实现IDisposable,因为您的类封装了一个IDisposable资源(它正在查看_proxy,尽管这并不完全是一件好事,因为它是静态的)。Code Rush 认为您正在使用的类型应该被显式清理,但您没有提供一种通过您的类来执行此操作的方法。

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

此外,鉴于上面的代码,这个类不应该实现IDisposable(除非有其他原因),因为_proxy资源是static. 至少在一般情况下,从实例中释放静态资源可能会导致问题。(在这种情况下,这显然没有问题,但这不是一个好习惯......)通常,静态变量的生命周期与实例成员的生命周期非常不同,因此自动处理它是不合适的。

于 2011-12-05T22:18:10.000 回答
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 是“借出”还是“给定”来解决此问题。其他情况可能需要使用引用计数包装器或其他复杂技术。

于 2011-12-06T00:55:59.940 回答