手动销毁C#对象

时间:2009-12-31 21:54:02

标签: c# destructor idisposable using

我对学习C#(来自Java& C ++背景)相当陌生,我对手动垃圾处理有疑问:是否可以手动销毁C#中的对象?我知道IDisposable接口,但是假设我正在处理一个我没写过的类而且它没有实现它?它不会有.Dispose()方法,因此using { }已经结束,而.Finalize始终是protectedprivate,所以这也不是一个选项

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

8 个答案:

答案 0 :(得分:28)

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

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

您可以做的是致电GC.Collect()强制进行一般性收集。但是,这几乎从来都不是一个好主意。

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

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

答案 1 :(得分:7)

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

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

答案 2 :(得分:7)

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

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

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

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

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

Jeff Richter最近为receiving a notification when garbage collection occurs发布了一个不错的小技巧。

Rico Mariani(MSFT)关于Garbage Collector Basics and Performance Hints的另一篇精彩文章

答案 3 :(得分:6)

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

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

答案 4 :(得分:4)

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

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

答案 5 :(得分:2)

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

答案 6 :(得分:2)

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

答案 7 :(得分:1)

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

aMatrix = null;

GC.Collect();

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