你怎么摆脱c#中的一个对象

时间:2009-02-13 01:55:20

标签: c# .net oop garbage-collection

在下面的c#代码中,如何删除不再有用的对象?是自动处理,还是需要做某事?

public void Test()
{
   object MyObject = new object();

   ... code ...
}

7 个答案:

答案 0 :(得分:18)

自动。当MyObject超出范围时(在测试结束时),它被标记为垃圾收集。在将来的某个时候,.NET运行时将为您清理内存

编辑: (我应该指出,为了完整起见,如果你在某处传递MyObject,它会被引用传递,并且不会被垃圾收集 - 只有当不再有对象的引用浮动时,GC才能自由地收集它)

编辑:在发布版本中,MyObject通常会在未使用时立即收集(有关详细信息,请参阅我的答案--dp)

答案 1 :(得分:5)

简短的回答是:除非它有非托管资源(文件句柄等),否则你不必担心。

更长的答案是更多参与。

当.NET决定要释放一些内存时,它会运行垃圾收集器。这将查找仍在使用的所有对象,并将其标记为这样。任何可能仍然被读取的局部变量(在任何线程的任何堆栈帧中)都像静态变量一样计为 root 。 (实际上我相信静态变量是通过实时类型对象引用的,它们通过实时AppDomain对象引用,但在大多数情况下,您可以将静态变量视为根。)

垃圾收集器查看根引用的每个对象,然后根据这些对象中的实例变量找到更多“实时”引用。它可以减少,查找并标记越来越多的对象为“实时”。完成此过程后,它可以查看对象的所有 rest 并释放它们。

这是一个非常广泛的概念图 - 但是当您想到垃圾收集,终结器,并发收集等的世代模型时,它会更加详细。我强烈建议您阅读Jeff Richter的{ {3}}详细介绍了这一点。如果你不想买这本书,他还有一篇CLR via C# two篇文章(从2000年开始,但仍然非常相关)。

当然,所有这些并不意味着您不必担心.NET中的内存使用和对象生存期。特别是:

  • 无意义地创建对象 会降低性能。特别是,垃圾收集器很快但不是免费的。在编码时寻找简单方法来减少内存使用量,但在您知道自己遇到问题之前进行微观优化也很糟糕。
  • 通过使对象的可达时间超过预期,可以“泄漏”内存。造成这种情况的两个相当常见的原因是静态变量和事件订阅。 (事件订阅使事件处理程序可以从事件发布者访问,但不能相反。)
  • 如果您使用的内存(以实时,可访问的方式)超过可用内存,则您的应用程序将崩溃。 .NET可以做很多事情来阻止它!
  • 使用非内存资源的对象通常会实现part。您应该在它们上面调用Dispose以在完成对象时释放这些资源。请注意,此不会释放对象本身 - 只有垃圾收集器才能这样做。 C#中的using语句是可靠地调用Dispose的最方便方式,即使面对异常也是如此。

答案 2 :(得分:4)

其他答案是正确的,除非您的对象是实现IDisposable接口的类的实例,在这种情况下您应该(显式或隐式地通过using语句)调用对象的Dispose方法。

答案 3 :(得分:3)

在优化代码中,可能并且可能在方法结束之前收集MyObject。默认情况下,Visual Studio中的调试配置将在调试开关打开且关闭优化开关的情况下构建,这意味着MyObject将保留在方法的末尾(以便您可以在调试时查看该值)。在优化关闭的情况下构建(在这种情况下调试无关紧要)允许在确定未使用MyObject后收集它。强制它在方法结束时保持活着的一种方法是在方法结束时调用GC.KeepAlive(MyObject)。

答案 4 :(得分:2)

这将强制垃圾收集器清除未使用的对象。

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

如果您想要收集特定对象。

object A = new Object();
...
A = null;
GC.collect();
GC.WaitForPendingFinalizers();

答案 5 :(得分:1)

它会自动处理。

答案 6 :(得分:1)

通常垃圾收集可以依赖于清理,但如果您的对象包含任何非托管资源(数据库连接,打开文件等),您将需要显式关闭这些资源和/或对象上的dispose方法(如果它)实现IDisposable)。这可能会导致错误,因此您需要小心处理这些类型的对象。简单地在使用文件后关闭文件并不总是足够的,因为关闭执行之前的异常会使文件保持打开状态。使用using块或try-finally块。

底线:“使用”是你的朋友。

相关问题