我仍然对C#的垃圾收集器感到困惑。文档说明当没有更多引用指向它时,对象是垃圾收集。
所以我的问题是,为什么这个对象不会立即被垃圾收集?没有提到它。我们假设背景类本身也没有创建引用。
public void StartGame() {
// the background instance is created, but no reference is kept:
new Background("landscape.png", speed);
}
答案 0 :(得分:2)
您所描述的内容与内存管理更相似,通过引用计数来检查是否在访问引用计数器时释放内存,通常是在构造或销毁引用对象时。 / p>
垃圾收集是一个略有不同的概念。通常不允许或不建议直接释放GC供电环境中的对象。相反,垃圾收集器偶尔运行(运行时决定何时执行),查找所有不再引用的对象并释放这些对象占用的内存。关键是,你不应该打扰(因为你什么都不做),确切的时候会发生。
答案 1 :(得分:2)
垃圾收集器就像是在你附近开车的垃圾车。一旦把它放在街道的一边,你就不能将它拿起你的垃圾。你必须等待它自己的条件。
垃圾收集器在理论上非常简单:停止世界,确定不再使用的东西,收集,恢复世界。但是因为这需要时间,开发人员使用复杂的算法来确定收集器何时启动以及收集什么,以使程序尽可能顺利地运行。一些垃圾通常不会影响您的程序。
如果您希望在对象超出范围时立即收集对象,并且您可能正在使用终结器来测试它。别!相反,实施IDisposable
并在完成后立即自行调用Dispose
方法。如果有的话,你不能随时依赖垃圾收集器来收集你的对象。这就是为什么BCL I / O类都实现IDisposable
来刷新流,关闭连接和清理内存。
或者如果你想保持你的对象,你需要来保持(间接)引用它。该对象可能只是在下一个垃圾收集周期中收集。
嗯,有一种不推荐的方式强制垃圾车收集垃圾,使用GC.Collect
:
GC.Collect();
这会暂时阻止你的程序收集所有垃圾。但是,当它存在于堆栈或其他位置时,这可能仍然无法清除您的Background
对象。您无法预测运行时将放置对象的位置以及何时将其释放,因此请确保在测试是否使用GC.Collect
收集对象之前至少退出创建对象的方法。
答案 2 :(得分:1)
C#中的垃圾收集器仅在某些时刻被调用并且是世代的。这意味着在GC的第一次通过时没有引用的对象将升级1代。最低代的垃圾收集方式比其他方式更频繁。
您可以阅读本文以了解更多信息:https://msdn.microsoft.com/en-us/library/ee787088%28v=vs.110%29.aspx
您也可以调用GC.Collect
方法,但不建议这样做,因为.NET几乎能够处理自己的内存并且调用此方法有点挫败了整个目的。
答案 3 :(得分:1)
好吧,如果你想检查一个对象是否会被垃圾收集,你可以通过执行以下操作,在你的代码中测试它是否符合收集标准。
稍微修改你的方法以进行测试,或者你可以引用一个在StartGame方法中设置的字段。
public void StartGame(out WeakReference reference)
{
reference = new WeakReference(new Background("landscape.png", speed));
}
调用方法后,您可以执行以下操作以查看它是否符合收集条件。
WeakReference reference;
StartGame(out reference);
GC.Collect();
GC.WaitForPendingFinalizers();
if (reference.IsAlive)
{
Console.WriteLine("Background is not eligible for collection");
}
这仅用于测试,否则你不应该调用垃圾收集器。