在下面的c#代码中,如何删除不再有用的对象?是自动处理,还是需要做某事?
public void Test()
{
object MyObject = new object();
... code ...
}
答案 0 :(得分:18)
自动。当MyObject超出范围时(在测试结束时),它被标记为垃圾收集。在将来的某个时候,.NET运行时将为您清理内存
编辑: (我应该指出,为了完整起见,如果你在某处传递MyObject,它会被引用传递,并且不会被垃圾收集 - 只有当不再有对象的引用浮动时,GC才能自由地收集它)
编辑:在发布版本中,MyObject通常会在未使用时立即收集(有关详细信息,请参阅我的答案--dp)
答案 1 :(得分:5)
简短的回答是:除非它有非托管资源(文件句柄等),否则你不必担心。
更长的答案是更多参与。
当.NET决定要释放一些内存时,它会运行垃圾收集器。这将查找仍在使用的所有对象,并将其标记为这样。任何可能仍然被读取的局部变量(在任何线程的任何堆栈帧中)都像静态变量一样计为 root 。 (实际上我相信静态变量是通过实时类型对象引用的,它们通过实时AppDomain对象引用,但在大多数情况下,您可以将静态变量视为根。)
垃圾收集器查看根引用的每个对象,然后根据这些对象中的实例变量找到更多“实时”引用。它可以减少,查找并标记越来越多的对象为“实时”。完成此过程后,它可以查看对象的所有 rest 并释放它们。
这是一个非常广泛的概念图 - 但是当您想到垃圾收集,终结器,并发收集等的世代模型时,它会更加详细。我强烈建议您阅读Jeff Richter的{ {3}}详细介绍了这一点。如果你不想买这本书,他还有一篇CLR via C# two篇文章(从2000年开始,但仍然非常相关)。
当然,所有这些并不意味着您不必担心.NET中的内存使用和对象生存期。特别是:
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块。
底线:“使用”是你的朋友。