First in this MSDN page
有一个标准的Dispose模式。并且有一个bool作为受保护的Dispose方法的参数,它告诉GC托管资源是否已经手动释放,这样GC就不需要关心它们了。
现在的问题是,在if (disposing) {}块中到底应该做什么?通常GC会清理托管资源,所以不需要做任何特殊的事情。但是由于在这个块中,需要显式地清理托管资源,这是否意味着只需要将对象中的所有字段和内容设置为null?
其次,在语言中只有一个析构函数(或终结器)不是更好吗?然后在GC设计中,只需放一点时间来确定析构函数是否已经被调用,这样就不需要对其进行垃圾回收,或者析构函数还没有被调用,GC应该清理它。我发现Dispose模式相当复杂,我非常困惑在哪个函数中清理什么,以及如何在派生类中清理。通过使用signle析构函数设计,GC只在还没有清理的时候清理它们,而不是在它们已经清理的时候清理它们。
问候
PS:那么这也是一个好的、更简单的清理对象的模式吗?
class Foo
{
bool unmanagedDisposed = false;
void Dispose() {/*clean up unmanaged resources*/ unmanagedDisposed = true;}
~Foo() {if (!unmanagedDisposed) Dispose();}
}因此,如果程序员知道并记得调用Dispose(),则在终结器中无事可做,否则将清除终结器中的非托管资源。在这里,我们不需要关心这些托管资源。
发布于 2013-01-28 22:14:24
在
if (disposing) {}块中到底应该做什么?
您清理了托管资源,即对您当时拥有的所有IDisposable对象调用Dispose()。
显式清理托管资源,这是否意味着只需将对象中的所有字段和内容设置为空?
不,这并不意味着这一点。它只与IDisposable对象有关。
在语言中只有一个析构函数(或终结器,不管它叫什么),不是更好吗?
我们只有一个析构函数,也就是终结器,而Dispose()不是它。这使得你段落的其余部分变得无关紧要。
我们有Disposable pattern和GC,它们是相关和协作的,但不是相同的。GC管理内存,并且只管理内存。IDisposable用于管理资源(流、连接、位图)。
发布于 2013-01-28 22:33:26
基本上,如果您有一个具有非托管字段或属性的类,则只需要使用dispose实现完整的~Destructor()模式。
如果您的所有字段和属性都是托管的,并且不是可处理的,那么您根本不需要实现IDisposable。
如果您的某个字段或属性是可处理的,那么您只需要实现IDisposable模式。你不一定要按照上面的模式去做所有的事情。
如果在最后一种情况下,字段或属性中确实有非托管资源(例如,指向某物的本机指针、除ADO以外的数据库连接或其他托管连接),则.net不知道如何在垃圾收集器回滚时清理它。
在这种情况下,您需要考虑清理对象的两个地方。要么它会被开发人员像他应该做的那样调用Dispose()来清理,要么他会忘记。如果他忘记了,而你有一个析构函数,那么它就会被放到终结队列中。
这就是Dispose(disposing)调用的用武之地。如果开发人员很好并且调用了Dispose(),那么您可以发送true,这样托管资源也可以被清理。
如果开发人员没有调用dispose,并且糟糕的对象最终出现在finalization队列中,那么在托管对象上调用Dispose()将抛出异常,因为它们不再存在。因此,在本例中,您发送了一个False,以便跳过托管资源并避免异常。我不确定这一点,但传说中说,在finalization队列中抛出异常会退出整个过程,甚至可能结束世界。所以别这么做。
https://stackoverflow.com/questions/14563878
复制相似问题