C# 这是我能为我做什么?

C# 这是我能为我做什么?,c#,refactoring,idisposable,coderush,C#,Refactoring,Idisposable,Coderush,我正在编写一个“学习程序”,并在学习过程中使用CodeRush重构工具。随着CodeRush的最新更新,它一直建议在我的程序中实现IDisposable。我知道MSDN是怎么说IDisposable的,我对它的功能有一个基本的了解,但因为我不知道实现它的所有含义,所以我一直忽略了这个建议。今天我决定进一步了解它,并同意了这个建议 这就是它添加到我的程序中的内容 class Program : IDisposable { static Service _proxy; public

我正在编写一个“学习程序”,并在学习过程中使用CodeRush重构工具。随着CodeRush的最新更新,它一直建议在我的程序中实现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的优势,还是我需要在代码中做一些事情来让它工作?我在上面加了一个断点,但从来没有通过调试器达到它,所以要么它不需要,要么我没有按预期的方式使用它。有人能帮我解释一下这对我有什么作用,或者我应该如何使用它,让它为我做点什么吗

在这种情况下,
coderrush
建议您实现
IDisposable
,因为您的类封装了
IDisposable
资源(它看到了
\u proxy
,但这并不完全是一件好事,因为它是静态的)。CodeRush认为您正在使用的类型应该被显式清理,但是您没有提供一种通过类进行清理的方法

这就是说,
IDisposable
是一个棘手的问题——在这种情况下,生成的代码实际上不是一个好的实现(即使
\u proxy
是一个实例变量)。我建议在这种情况下不要使用析构函数。这将导致GC中出现性能问题,在这种情况下,这无助于安全性,因为封装的资源应该处理您忘记为您调用
Dispose()
的情况。有关详细信息,请参阅,尤其是


此外,由于
(代理
资源是
静态的
,因此此类不应在给定上述代码的情况下实现
IDisposable
(除非有其他原因)。至少在一般情况下,从实例处理静态资源可能会导致问题。(在这种情况下,这显然没有问题,但不是一个好的做法…)通常,静态变量的生存期与实例成员的生存期非常不同,因此自动处理它是不合适的。

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

  • 其他一些对象也将至少在Foo需要时保存该引用,并负责对其调用Dispose,因此Foo应该让其他对象负责Dispose。
  • 持有引用的对象将是最后一个使用有问题的IDisposable对象的对象;如果Foo不调用Dispose,其他任何东西都不会调用。在这种情况下,Foo必须确保在不再需要另一个对象的Dispose方法(Foo)并且在放弃它之前调用它。处理这个问题最惯用的方法是,Foo实现IDisposable.Dispose,其Dispose方法对IDisposable对象调用Dispose,该对象包含最后有用的引用。
    在某些情况下,类设计器可能不知道其类是否将保存对IDisposable对象的最后一个有用引用。在某些情况下,可以通过让类构造函数指定传递给构造函数的IDisposable是“借出”还是“给定”来解决此问题。其他情况可能需要使用引用计数包装器或其他复杂技术。

    这似乎是正确的。IDisposable的概念是,对象将引用非托管资源。由于GC不会清理非托管资源,因此对象需要说。。“等等,在我被摧毁之前,我得打扫一下房子。”。每当您的对象使用非托管代码/调用或包含实现IDisposable的对象时,您也应该在实现IDisposable和/或清理非托管代码的任何对象上实现IDisposable和调用Dispose()。此代码建议可能会引入非常糟糕的行为-这是他们建议中的一个错误。@tipx:trace Dispose(false)的实际功能。伙计们,谢谢你们的注释。我们将尽快修复实现IDisposable功能。我们将在下一次更新中修复此功能,我们还将改进对字段的分析,以确保字段明确拥有其内容,并且这些内容不会在任何其他地方共享(引用/传递)。完全正确--99%的时间,您不需要IDisposable的析构函数,因为您只是封装了一个已经有析构函数的资源。@JoelCoehoorn在这种情况下更糟糕,因为
    \u proxy
    是静态的-处理它是完全不合适的。建议使用终结器,以防后代类需要重写Dispose(bool)方法进行非托管清理。当然,派生类可以从它自己的终结器调用Dispose(false),这就解决了问题,尽管它与“官方”模式略有不同。就个人而言,我更喜欢将类标记为密封的,并完全避免这个问题。@DanBryant是的-在我看来,子类直接添加非托管资源是非常不合适的。它使用的资源应该包装在它自己的托管处理程序中,这样就消除了这个问题。。。不过,如果你走这条路,那么它可以像你提到的那样,执行自己的析构函数,这将更加“为游戏付费”