C# 有关C Dispose如何工作的更多信息

C# 有关C Dispose如何工作的更多信息,c#,garbage-collection,C#,Garbage Collection,在试图理解IDisposable时,我有几个问题,大多数答案都没有明确说明 如果我们对一个对象调用dispose,那么是在那个时候处理对象,还是只处理我们想要清理的类成员,然后整个对象将被GC销毁 在我们抑制dispose方法中的终结器之后,GC还会清理我们在dispose中没有清理的所有类成员吗 一旦一个对象的所有引用都消失了,它将以非确定性的方式被垃圾收集。 从MSDN: 当满足下列条件之一时,会发生垃圾回收 正确: 系统的物理内存不足。 托管堆上已分配对象使用的内存 超过可接受的阈值。这意

在试图理解IDisposable时,我有几个问题,大多数答案都没有明确说明

如果我们对一个对象调用dispose,那么是在那个时候处理对象,还是只处理我们想要清理的类成员,然后整个对象将被GC销毁

在我们抑制dispose方法中的终结器之后,GC还会清理我们在dispose中没有清理的所有类成员吗


一旦一个对象的所有引用都消失了,它将以非确定性的方式被垃圾收集。 从MSDN:

当满足下列条件之一时,会发生垃圾回收 正确:

系统的物理内存不足。 托管堆上已分配对象使用的内存 超过可接受的阈值。这意味着 托管堆上已超过可接受的内存使用率。这 阈值在进程运行时不断调整。 调用GC.Collect方法。几乎在所有情况下,您都没有 调用此方法,因为垃圾收集器连续运行。 此方法主要用于特殊情况和测试


一旦一个对象的所有引用都消失了,它将以非确定性的方式被垃圾收集。 从MSDN:

当满足下列条件之一时,会发生垃圾回收 正确:

系统的物理内存不足。 托管堆上已分配对象使用的内存 超过可接受的阈值。这意味着 托管堆上已超过可接受的内存使用率。这 阈值在进程运行时不断调整。 调用GC.Collect方法。几乎在所有情况下,您都没有 调用此方法,因为垃圾收集器连续运行。 此方法主要用于特殊情况和测试


1当您对对象调用dispose时,只需运行其dispose方法中的代码即可。当然,这段代码可能会为其一个或多个字段调用Dispose,但并不要求这样做

它也可以通过base.Dispose调用基类的Disposetrue,如果有的话,但这是使用Dispose习惯用法;Disposebool不是IDisposable接口的一部分


2仅对调用SuppressFinalize的特定对象抑制终结器。它不会影响任何其他对象,包括为其调用SuppressFinalize的对象的任何Hold by字段。

1在对象上调用dispose时,所发生的一切是运行其dispose方法中的代码。当然,这段代码可能会为其一个或多个字段调用Dispose,但并不要求这样做

它也可以通过base.Dispose调用基类的Disposetrue,如果有的话,但这是使用Dispose习惯用法;Disposebool不是IDisposable接口的一部分


2仅对调用SuppressFinalize的特定对象抑制终结器。它不会影响任何其他对象,包括为其调用SuppressFinalize的对象的任何Hold by字段。

首先,关于此主题,这里有大量重复的问题。如果真的没有其他答案明确回答你的问题,它们在这里,但我希望这是一个重复关闭

首先,Dispose只是一种方法,一种普通的方法。它根本不处理垃圾收集

那么Dispose做什么呢?它应该用于清理非托管资源,例如文件句柄、窗口句柄等.NET垃圾收集器不知道的东西

所以要回答问题1:是的,当你对一个对象调用Dispose时,它会被放置在那里,然后。类上没有设置用于指示以后清理的标记

由于Dispose不处理垃圾收集,因此可以在处理对象后轻松保留对该对象的引用,并且不会对其进行垃圾收集。垃圾回收仅在不再引用对象时发生。即使未对对象调用Dispose,也可能发生这种情况,但不会发生,因为您对对象调用Dispose

第二个问题:当GC在完成终结器循环后收集对象时,GC将清除该对象+它引用的任何对象,这些对象不再有任何引用遗留在对象中的引用之外。这在某个时刻发生,也不一定同时发生


抑制终结器只是确保GC不会做超出必要的工作,比如说,当您找到这个对象并确定它符合收集条件,然后继续收集它,我已经完成了“终结”清理,所以您不必这样做。

首先,关于这个话题,这里有很多重复的问题。如果真的没有其他答案明确回答你的问题,它们在这里,但我希望这是一个重复关闭

冷杉 t、 Dispose只是一种方法,一种普通的方法。它根本不处理垃圾收集

那么Dispose做什么呢?它应该用于清理非托管资源,例如文件句柄、窗口句柄等.NET垃圾收集器不知道的东西

所以要回答问题1:是的,当你对一个对象调用Dispose时,它会被放置在那里,然后。类上没有设置用于指示以后清理的标记

由于Dispose不处理垃圾收集,因此可以在处理对象后轻松保留对该对象的引用,并且不会对其进行垃圾收集。垃圾回收仅在不再引用对象时发生。即使未对对象调用Dispose,也可能发生这种情况,但不会发生,因为您对对象调用Dispose

第二个问题:当GC在完成终结器循环后收集对象时,GC将清除该对象+它引用的任何对象,这些对象不再有任何引用遗留在对象中的引用之外。这在某个时刻发生,也不一定同时发生


抑制终结器只是确保GC不会做超出必要的工作,即当您找到此对象并确定其符合收集条件时,继续收集它,我已经完成了“终结”清理,所以您不必这样做。

首先,也是最重要的一点,您需要了解处理对象和垃圾收集对象是-确保不要混淆两者

如果我们对一个对象调用dispose,唯一发生的事情就是调用该方法。可能Dispose方法随后会继续调用,但它可能什么也不做——这完全取决于实现

当我们调用GC.SuppressFinalize时,唯一发生的事情是,它请求GC在收集对象时不要调用对象终结器,就好像对象一开始没有终结器一样


碰巧的是,对于具有终结器的对象,一种常见的模式是同时实现IDisposable,以便可以确定地清理非托管资源-如果发生这种情况,则GC无需调用终结器,因为在调用Dispose时,终结器中本应完成的工作已经执行了-调用GC.SuppressFinalize只是对GC的一个友好提示,它实际上并不需要调用终结器。

首先,也是最重要的一点,您需要了解处理对象和垃圾收集对象是-确保不要混淆两者

如果我们对一个对象调用dispose,唯一发生的事情就是调用该方法。可能Dispose方法随后会继续调用,但它可能什么也不做——这完全取决于实现

当我们调用GC.SuppressFinalize时,唯一发生的事情是,它请求GC在收集对象时不要调用对象终结器,就好像对象一开始没有终结器一样


碰巧的是,对于具有终结器的对象,一种常见的模式是同时实现IDisposable,以便可以确定地清理非托管资源-如果发生这种情况,则GC无需调用终结器,因为在调用Dispose时,终结器中本应完成的工作已经执行了-调用GC.SuppressFinalize只是对GC的一个友好提示,它毕竟不需要调用终结器。

您需要阅读Ravi发布的内容,了解垃圾收集在C中的工作原理。Dispose只是一个关闭文件、网络连接、SQL server连接的方便地方,等。它不会释放内存。IDisposeable在任何方面都不是神奇的。它确实与GC或类似的东西有任何联系。这只是一种模式,如果它不存在于.NET中,您可以自己编写该接口来达到相同的效果。处理对象和垃圾收集是-请确保不要混淆两者!您需要阅读Ravi发布的内容,了解垃圾收集在C中的工作原理。Dispose只是一个方便的关闭文件、网络连接、SQL server连接等的地方。它不会释放内存。IDisposable在任何方面都不是神奇的。它确实与GC或类似的东西有任何联系。这只是一种模式,如果它不存在于.NET中,您可以自己编写该接口来达到相同的效果。处理对象和垃圾收集是-请确保不要混淆两者!