我正在阅读有关如何实现IDisposable的MSDN文章,我不确定文章中引用的托管和本机资源之间的区别.
我有一个类在处理时必须处理它的两个字段.我应该将它们视为托管(仅在处置= true时处置)或本机资源吗?
为Brian的回答添加一点,以及您的评论/问题:
托管/非托管资源之间的区别在于垃圾收集器了解托管资源,并且不知道非托管资源.我知道答案不是很具体,但差别很大.
为了帮助在这里绘制线条,这是GC运行和清理内存的简短版本(可能还有很少的错误):
垃圾收集器知道所有托管对象,但是当垃圾收集运行时,它最初不知道任何给定对象是否仍在使用中或者是否可以被释放.它通过最初将所有对象标记为垃圾,然后从应用程序根遍历到所有引用的对象来确定它是否可以清理对象.具有回到根的关系的每个对象(引用,直接或间接)被标记为可达,并且不再被视为垃圾.GC运行通过每个可到达的对象后,它会清理其余的,因为它们不再使用.
几乎在所有使用.NET框架对象的情况下,都可以确保管理对象(.NET提供几乎所有非托管资源的托管包装,以确保它们得到正确清理); 挂钩到Win32 API(或执行此操作的组件)的其他第三方组件是可能引起关注的对象.
有些.NET对象可以被认为是有些不受管理的.图形库的组件就是一个例子.
大多数".NET内存泄漏"并不是真正意义上的内存泄漏.通常,当您认为已从使用中删除了某个对象时,它们就会出现,但实际上该对象仍然具有对该应用程序的一些引用.一个常见的例子是添加eventhandler(obj.SomeEvent + = OnSomeEvent -or- AddHandler obj.SomeEvent,AddressOf OnSomeEvent)而不删除它们.
这些"挥之不去的引用"在技术上并不是内存泄漏,因为您的应用程序仍在技术上使用它们; 但是,如果有足够的应用程序,您的应用程序可能会受到严重的性能影响,并可能显示资源问题的迹象(OutOfMemoryExceptions,无法获得窗口句柄等).
我是一名中级.NET开发人员,不幸的是他第一时间了解这些问题.我建议使用ANTS Profiler来帮助熟悉延迟引用(有一个免费试用版),或者如果你想通过WinDbg和SOS.DLL来查看托管堆,可以进行更多细节研究.如果您决定研究后者,我建议您阅读Tess Ferrandez的博客; 她有很多关于有效使用Windbg的精彩教程和建议
托管资源是另一种实现的托管类型IDisposable
.您需要调用您使用的Dispose()
任何其他IDisposable
类型.本机资源是托管世界之外的任何东西,例如本机Windows句柄等.
编辑:回答评论中的问题(评论太长)
不,这只是一种托管类型.正确构造的类型(未实现)IDisposable
将由垃圾收集器处理,您不必执行任何其他操作.如果您的类型直接使用本机资源(例如,通过调用Win32库),则必须IDisposable
在您的类型上实现并处理该Dispose
方法中的资源.如果您的类型使用由另一个实现的类型封装的本机资源IDisposable
,则必须Dispose()
在类型的Dispose
方法中调用此类型的实例.