设计/编译时类型hard to find是IDisposable,但没有正确处理。在运行时有哪些方法可以找到它们?
答案 0 :(得分:7)
如果您的类型资源非常耗材,但,则优先实施IDisposable
,这只是良好做法,无法强制执行编译器。
要使滥用IDisposable
更明显,可以做的一件事就是在throw
中制作assert
或finalizer
(请记住,如果您的类型被处理掉)正确地说,终结者不会被调用,因为你将在你的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中或免费下载)可以检测到这一点。
虽然偶尔会出现假阴性/阳性。