Dispose模式:我如何知道什么是受管理的,什么是非托管的?

6
阅读Dispose pattern的相关文档时,我发现文档反复提到“清理托管和非托管代码”。在Dispose方法的规范实现中,我看到特定的流程(取决于disposing是true还是false)专门用于清理托管对象与非托管对象。
但是,作为一个卑微的新手,我怎么知道哪些类型是托管的,哪些是非托管的呢?
5个回答

5

Unmanaged是指原生的Win32对象,主要包括句柄和对原始COM对象的引用。这些资源不受.NET CLR(公共语言运行时)控制或管理。


没错,但是一个纯粹的.NET开发人员,年轻到没有使用过Win32、COM等等,他怎么会“知道”一个资源不受CLR控制,或者更糟糕的是,依赖于一个不受CLR控制的资源?我的意思是,你怎么“知道”,比如说,一个句柄是非托管的?可能是经验。但在没有这种经验的情况下,一个新手程序员如何才能每次都做对呢?我认为,例如IDisposable接口的存在并不足够;普通程序员并没有被教导要检查每个类型的文档是否提到了IDisposable。 - Jeff Stewart
1
我持相反意见。如果IDisposable存在,则应该丢弃。没什么好说的。这样,年轻的程序员就不必接触到COM的创伤了。 - John Saunders

3

简而言之,任何实现IDisposable接口的内容都需要在你的Dispose方法中调用。如果你漏掉了某些内容(或者没有在应该使用IDisposable接口的时候使用),FxCop也会告诉你。


虽然这并没有回答问题,但我不再相信有一个好的答案存在。这提供了解决当程序员无法判断类型的“可管理性”时出现的问题的最佳实际解决方案,但我认为想要确定性启发式来做出判断的程序员只是纯粹的运气不好。 - Jeff Stewart

2
“管理或未管理”并不重要。如果一个类实现了IDisposable接口,当你完成使用这个对象时,应该调用Dispose()方法。或者(最好的方式)使用using语句,使得当对象超出范围时自动调用Dispose()。
@ Rob:
答案仍然是一样的。如果你的类管理任何实现IDisposable接口的内部对象,那么它也应该实现IDisposable接口。在Dispose()方法中,调用这些对象的Dispose()方法。

我认为这个问题是从设计IDisposables的角度来看的——即在处理dispose和finalize时应该释放哪些资源,哪些不应该释放。 - Rob
1
@Thorarin - 我认为Rob想表达的是,如果你实现了经典的dispose模式,你会有一个isDisposing标志来指示它是否由于调用dispose或由于执行finaliser而处于disposing状态。在后一种情况下,您需要小心不要处理其他托管对象,因为它们可能已经被垃圾回收。只有在从Dispose()方法显式调用时才可以安全地处理这些对象。然而,非托管资源在两种情况下都应该被处理。 - Rob Levine
我在这方面倾向于采用盖世太保的方法:如果最终器被调用了,就大声向程序员抱怨,让他们修复代码。 - Thorarin

0

如果你不知道,你正在使用的类型可能是托管的。

非托管类型指的是不安全的类型,即不符合CLR安全要求的类型。

链接到很好的定义

更新

我不明白为什么会有人踩?问题明确是如何区分托管和非托管类型?

所有其他答案都在回答IDispose问题,而不是托管/非托管问题!?

更新2

仍然没有解释第二个踩的原因...

我同意,IDisposable对象应该始终被处理,但这并不能回答关于托管和非托管的问题。


与我之前的评论类似,您如何“知道”一个类型不符合CLR安全要求?即,如果我编写一个Reflector插件来报告所选类型的“非托管性”,那么我的插件将检查该类型上的什么内容以做出明确的判断? - Jeff Stewart

0
我建议在使用完资源后直接销毁它们。通常依赖于系统资源的任何东西,例如套接字和流资源,都需要显式释放。如果不确定,请先处理掉。这样可以在长期内节省大量调试麻烦。通常,当您调用未使用.NET编写的代码时,可以假定它不是“托管代码”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接