手动销毁C#对象

我对学习C#(来自Java和C ++背景)相当新,我有一个关于手动垃圾处理的问题:是否有可能手动销毁C#中的对象? 我知道IDisposable接口,但是假设我正在处理一个我没写过的类而且它没有实现它? 它不会有.Dispose()方法,因此using { }是out,而且.Finalize总是protectedprivate因此也不是一个选项。

(我只是想在这种情况下学习C#中可能的内容 。我想如果所有其他方法都失败了,我可以inheritance假设的ImNotDisposable类,以便它实现IDisposable。)

您不要手动销毁.Net对象。 这就是托管环境的全部意义所在。

事实上,如果对象实际上是可达的,意味着你有一个引用,你可以用来告诉GC要销毁哪个对象,收集该对象是不可能的。 GC 永远不会收集任何仍可访问的对象。

你可以做的是调用GC.Collect()来强制一般集合。 但是,这几乎从来都不是一个好主意。

相反,最好只是假装任何不使用非托管资源且程序中任何其他对象无法访问的对象立即被销毁。 我知道这不会发生,但此时对象只是一块内存,就像其他任何东西一样; 你不能收回它,它最终会被收集,所以你可能也死了。

关于IDisposable最后一点说明。 您应该只将它用于包装非托管资源的类型:套接字,数据库连接,gdi对象等,以及偶尔的事件/委托订阅。

如果无法访问该对象,则可以调用GC.Collect()并销毁该对象。 IDisposable的概念与CLR无关,主要是用户代码实现执行额外的处理逻辑。 在对象上调用Dispose()不会将对象本身从内存中释放出来,尽管它可以很好地处理此对象引用的任何资源。

我应该补充说,虽然我所说的是一种实现这一目标的方法,但在99.9999%的应用程序中,您永远不应该调用GC.Collect()因为它通常会降低应用程序的性能而不是改进它。

虽然您可以触发垃圾收集(您需要为所有代触发GC,因为您无法确定可终结对象所在的那一代),但您不一定强制完成特定对象。 您只能依赖于有关垃圾收集器如何工作的假设。

此外,由于终结发生在自己的线程上,因此应在触发垃圾收集后调用WaitForPendingFinalizers 。

 GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); 

正如其他人所指出的,这实际上可能会损害您的应用程序的性能,因为不必要地调用GC可以将其他短期对象推向更高代,这些对象收集起来更昂贵并且收集频率更低。

一般来说,实现终结器(析构函数)并且不实现IDisposable的类是不受欢迎的。 任何实现IDisposable的东西都应该调用它的终结器逻辑并且在垃圾收集中完成最终化。

Jeff Richter最近发布了一个很好的小技巧,用于在垃圾收集发生时收到通知 。

Rico Mariani(MSFT)关于垃圾收集器基础知识和性能提示的另一篇精彩文章

不,你不能销毁一个特定的对象。

可以调用垃圾收集器,它会查找要销毁的对象,但这几乎不是一个好主意。

可以强制垃圾收集器在你想要销毁的变量超出范围之后运行,但是你通常不希望这样做,因为垃圾收集器如果要做自己的工作就更有效率。

强制垃圾收集可以使用GC.Collect完成,但不要这样做。 在我作为.NET开发人员的10年中,我从未需要它。

以确定的方式破坏对象是不可能的。 CLR确定何时回收标记的对象。 这意味着虽然您可以标记对象以进行回收,并确保整理托管和非托管资源以进行处置(通过实现IDisposable模式),但释放内存的实际时间取决于CLR。 这与C ++不同,在C ++中你实际上可以删除某些东西然后它会被释放。

编码愉快,

斯科特

无法手动销毁一个“像C ++删除”这样的对象,所有你能做的就是关闭对象获取的所有独占资源,并将对该对象的所有引用都置空,这样GC就可以收集它,也不用调用GC .Collect()自己,GC过程很昂贵,因为它必须暂停所有其他线程以安全地从内存中收集对象,所以只需信任GC,它就会在需要时启动。

假设你有一个类矩阵,你创建了两个矩阵对象aMatrix和bMatrix。 在C#中,您可以手动销毁(完成)一个对象,如下所示:

aMatrix = NULL;

所以GC.Collect();

垃圾收集器会注意到你的aMatrix是NULL并将销毁(敲定)它。 这是一个好主意是一个不同的故事。