0

首先在这个 MSDN 页面

有一个标准的 Dispose 模式。并且有一个bool作为protectedDispose方法的参数来告诉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(),在终结器中什么都不做,否则在终结器中清理非托管资源。在这里,我们不需要关心那些托管资源。

4

2 回答 2

1

~Destructor()基本上,如果您有一个具有非托管字段或属性的类,您只需要使用 dispose 实现完整模式。

如果您的所有字段和属性都是托管的并且不是一次性的,那么您根本不需要实现 IDisposable。

如果您的字段或属性之一是一次性的,那么您只需要实现 IDisposable 模式。您不必完全按照上述模式进行操作。

如果在最后一种情况下,您在字段或属性中确实有非托管资源(例如,指向某物的本机指针、ADO 以外的数据库连接或其他托管连接),那么 .net 不知道在垃圾收集器时如何清理它滚来滚去。

在这种情况下,您需要考虑清理对象的两个地方。要么它会像他应该的那样由开发人员调用来清理Dispose(),要么他会忘记。如果他忘记了,而你有一个析构函数,那么它就会被放到一个终结队列中。

这就是Dispose(disposing)调用的来源。如果开发人员很好并且调用了Dispose(),那么您发送 true 以便也可以清理托管资源。

如果开发人员没有调用 dispose 并且可怜的对象最终出现在终结队列中,那么调用Dispose()托管对象将引发异常,因为它们不再存在。因此,在这种情况下,您发送 False,以便跳过托管资源并避免异常。我不确定这一点,但传说中在终结队列上抛出异常会退出整个过程,甚至可能结束世界。所以不要这样做。

于 2013-01-28T14:33:25.630 回答
1

究竟应该在if (disposing) {}块内做什么?

您清理托管资源,即调用Dispose()您当时拥有的所有 IDisposable 对象。

要显式清理托管资源,这是否意味着只需将对象中的所有字段和内容设置为空?

不,不是那个意思。它仅与 IDisposable 对象有关。

语言中只有一个析构函数(或终结器)不是更好吗?

我们只有一个析构函数,也就是终结器, Dispose()不是吗。这使您段落的其余部分无关紧要。

我们有 Disposable 模式和 GC,它们是相关的和合作的,但并不相同。GC 管理内存并且只管理内存。IDisposable 用于管理资源(流、连接、位图)。

于 2013-01-28T14:14:23.797 回答