如何判断我的`IDisposable`类型没有明确处理?

时间:2010-06-23 07:20:10

标签: .net garbage-collection

设计/编译时类型hard to find是IDisposable,但没有正确处理。在运行时有哪些方法可以找到它们?

2 个答案:

答案 0 :(得分:7)

如果您的类型资源非常耗材,,则优先实施IDisposable,这只是良好做法无法强制执行编译器

要使滥用IDisposable更明显,可以做的一件事就是在throw中制作assertfinalizer(请记住,如果您的类型被处理掉)正确地说,终结者不会被调用,因为你将在你的dispose方法中调用GC.SuppressFinalize。以下程序在应用程序完成时显示调试器输出窗口中的错误,因为Hog未正确处理。

    class Program
    {
        static void Main(string[] args)
        {
            new Hog( ) ;
        }
    }

    class Hog : IDisposable
    {          
        public void Dispose( )
        {
            Dispose( true ) ;
            GC.SuppressFinalize( this ) ;
        }

        protected virtual void Dispose( bool disposing )
        {
            GC.SuppressFinalize( this );
        }

        ~Hog( )
        {
            Debug.Fail( @"You didn't dispose me!" ) ;
            Dispose( false ) ;
        }
    }

您将在调试器中看到以下错误:

---- DEBUG ASSERTION FAILED ----
---- Assert Short Message ----
You didn't dispose me!
---- Assert Long Message ----
    at Hog.Finalize()

,如果您确实正确使用了一次性对象,例如:

static void Main(string[] args)
{
    using (new Hog())
        ;
}

......你什么都看不到。

为了使事情更有用,您可以在构造函数中记录当前堆栈跟踪并将其转储到析构函数中。所以新的,更有用的Hog看起来像:

    class Hog : IDisposable
    {
        readonly StackTrace _stackTrace ;

        public Hog( )
        {
#if DEBUG
            _stackTrace = new StackTrace();
#endif
        }

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

        protected virtual void Dispose( bool disposing )
        {
            GC.SuppressFinalize( this );
        }

        ~Hog( )
        {
#if DEBUG
            Debug.WriteLine("FinalizableObject was not disposed" + _stackTrace.ToString());
#endif
            Dispose( false ) ;
        }
    }

并使用它(不处理它)会在调试器输出窗口中显示:

FinalizableObject was not disposed   at ConsoleApplication1.Hog..ctor()
   at ConsoleApplication1.Program.Main(String[] args)
   at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

答案 1 :(得分:1)

像FxCop这样的代码分析工具(包含在Visual Studio的Team Editions中或免费下载)可以检测到这一点。

虽然偶尔会出现假阴性/阳性。