MSDN的实例代码展示了如何实现Dispose()方法,其中将对已经释放的托管资源的引用设置为null(_resource = null
),但这个操作不在if (disposing)
块中执行:
protected virtual void Dispose(bool disposing)
{
// If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
if (!_disposed)
{
if (disposing) {
if (_resource != null)
_resource.Dispose();
Console.WriteLine("Object disposed.");
}
// Indicate that the instance has been disposed.
_resource = null;
_disposed = true;
}
}
_resource = null
是否应该放在这个代码块内?如果调用Dispose(false)
,_resource
将为null,无法随后进行处理!但是,如果先前没有处理_resource
,那么在对象(包括_resource
成员字段)即将被垃圾收集时,在此时将其设置为null有什么必要呢?当然,“Dispose(false)”(实际上)只会在最终化期间由运行时调用。但是,如果之前未处理
_resource
,则在对象(包括_resource
成员字段)即将被垃圾收集时,在这一点上将其设置为null的必要性是什么?在经过大量阅读后,似乎不需要将引用设置为空,但如果您有理由相信包含类(正在处理的类)可能不会很快被垃圾收集,则对于“重”成员对象可能是一个好主意。
知道对象处理不能保证消耗代码已将对象“释放”。处置对象可能会被保留(在集合或其他位置)用于各种目的,或者只是错误的。我可以想象一个使用集合中的对象然后处置它们的应用程序,但在集合中保留它们以供稍后的进程执行删除和记录最终状态(或类似的操作)。
因此,结论如下:
1.将对“重”成员对象的引用设置为空会释放它们进行垃圾收集,即使处理的对象没有被释放。
2.清除所有对象的引用是过度的。
3.因此,在两个方面上都不重要,位置
_resource = null
语句(原始问题):(A)在阅读上述内容之后才考虑使用它; (B)在MSDN示例中,它对Dispose(true)
和Dispose(false)
执行,但后者仅在对象终止并且即将被垃圾收集时发生!if (disposing) {
if (_resource != null) {
_resource.Dispose();
_resource = null;
}
}
这样可以将所有_resource
代码放在一起。还有其他想法吗?
更多阅读:
Console.Writeline()
是示例代码。使用Trace.Writeline()
会更好吗?另外,没有缺少的括号——它在if
行的末尾(不符合StyleCop规范)。 - Kevin P. Rice_resource
为 null 并且没有调用.Dispose()
,它仍然会写入“Object disposed.”。 我的意思是 最内层 的if
。 - Marc Gravell_resource = null
没有意义(请参见Igor Zevaka在https://dev59.com/dXA85IYBdhLWcg3wJf4Z的答案)。 - Kevin P. Ricethis
而不是_resource
,所以我向你提交代码按照原样是正确的。 - Kevin P. Rice