以下代码来自MSDN:Idisposable pattern
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;
_disposed = true;
不包含在if(disposing)语句块中吗?
对我来说,我可能会这样写:if (disposing) {
if (_resource != null) {
_resource.Dispose();
_resource = null;
_disposed = true;
}
Console.WriteLine("Object disposed.");
}
我的版本出了什么问题?
答案 0 :(得分:1)
在调用Dispose()之后,资源应始终标记为已丢弃,否则可能会遇到问题。因此,即使_resource为null,您也需要将其标记为已处置。
正在运行
_resource = null;
即使资源首先为空,也不会受到伤害。
答案 1 :(得分:1)
是;)
好的,_resource = null - 正如你所说的那样有恕我直言。示例代码在这里很邋,抱歉;)我也喜欢你的方式。
但是,_disposed = true,如果_resource存在则是独立的。如果_resource指针尚未初始化,则应该设置它,因此它应该直接位于Console.WriteLine之上。想象一下_resource是一个文件处理程序的情况,它在类中的方法调用期间打开 - 可能存在创建类的情况,但文件处理程序没有,在这种情况下,dispose也必须起作用。
if (disposing) {
if (_resource != null) {
_resource.Dispose();
_resource = null;
}
_disposed = true;
Console.WriteLine("Object disposed.");
}
是我写它的方式。
答案 2 :(得分:1)
MSDN概述的模式是实现IDisposable的唯一正确方法,因为它考虑了最终结果。您需要仔细查看IDisposable实现:
public void Dispose()
{
Dispose(true);
// Use SupressFinalize in case a subclass
// of this type implements a finalizer.
GC.SuppressFinalize(this);
}
这会调用你的dispose方法,表明它是一个真正的处理方法,并阻止进一步的最终确定。
在最终确定期间呼叫任何其他对象是不安全的,所以这就是你想要设置的原因:
_resource = null;
_disposed = true;
以防止任何进一步的错误发生。
这是MSDN上的终结和IDisposable上的good info。
答案 3 :(得分:1)
Dispose(bool)
函数通常从Dispose()
和Finalizer(在C#中命名为~Class)中调用。当终结器调用时,垃圾收集已经在进行中,并且没有定义不同对象之间的垃圾收集顺序。垃圾收集器可能已经很好地销毁了_resource
,所以只有当Dispose(bool)
从Dispose()
调用我们想要销毁“子资源”时才会这样做(对于托管资源,这是真的,不受管理应始终释放资源)
答案 4 :(得分:1)
有问题的2行的位置在MSDN模式中是正确的
原因是在正确的实现中,正如我在下面引用的博客中所提供的,Dispose(bool)的重载版本在Finalizer的调用中传递值false
。请注意,如果您确实需要Finalizer,则应该只实现Finalizer。话虽如此,这些行的位置不应根据您是否实现Finalizer而有所不同。
我在博客上写了一个改进版的IDisposable模式 - How do you properly implement the IDisposable pattern?。您会发现我提供的此模式的实现与MSDN上发布的实现略有不同。恕我直言,这还不够。您必须同意MSDN上发布的大量示例和示例都是“hacky”,并且不会像在“现实世界”中那样完成它们。