当大家需要自己实现一个Dispose时,网上的经典例子都是这样写的:
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true);
}
protected virtual void Dispose(bool isDisposing)
{
if (_alreadyDisposed)
return;
if (isDisposing)
{
// TODO: 释放托管资源
}
// TODO: 释放非托管资源
_alreadyDisposed = true;
}
~ResourceHolder()
{
Dispose(false);
}
问题1:_alreadyDisposed为了防止Dispose反复被调用,但没防止SuppressFinalize反复被调用,不能算是很好的写法吧?
问题2:真有必要区分释放托管资源和非托管资源吗?因为托管资源也不需要我们来释放,实际写代码中几乎我没碰到过要写在 释放托管资源区 的代码,谁能告诉我isDisposing参数的优点到底在哪里,除了用来区分在Dispose和析构里的调用外?
------解决思路----------------------
托管资源你不用管,非托管的,你最好处理一下,不过对于托管的,也建议你别置之不理
------解决思路----------------------
当你不手动调用Dispose,而完全依赖GC回收时,托管资源的释放就会被调用两次(托管资源自己的析构函数执行了一次,然后外面那个函数的析构执行时还会调用一次Dispose),虽然不会报错,但是不调用更好
------解决思路----------------------
“_alreadyDisposed为了防止Dispose反复被调用”这并不准确。它主要是要防止“重入”。
程序中经常会有并发处理,有些处理中就需要判断一下这个状态,否则就会报错。比如说窗体上有一个监听设备消息的机制,当有消息来的时候就把消息处理了之后交给窗体绘制新的报表,或者再把报表发给另一个设备。如果窗体已经被用户点击Close按钮而正在关闭(清理环境)的过程中,设备异步监听到有消息可以读取,它就得先判断一下窗体是不是正在清理,如果清理就不能读取消息以及进行后续的计算、绘制、传输等操作了,否则就会产生一些列崩溃事件。即使不崩溃,也没有必要做这些。
所以它不一定是为了对象自己“防止被反复调用”,而是一个信号灯去通知其它并发机制“我正在关闭,因此从现在开始就立刻不要再跟我交互了”。