垃圾收集器C#,关于’清除’对象的问题

我读了一些关于垃圾收集的信息(它是如何工作的等等)。 我试着理解它是如何运作我的例子,但我认为我有问题。 我知道垃圾收集器运行时:
内存不足,
你调用GC.Collect()。
这是我的代码:

public partial class Form1 : Form { public Testing _d; public Boolean _first = false; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { if (!_first) { _d = new Testing(); int test = _d.DoSomething("example"); } } private void button2_Click(object sender, EventArgs e) { _first = true; } private void button3_Click(object sender, EventArgs e) { //if (_first) //{ // _d = null; //} GC.Collect(); } } public class Testing { private ASCIIEncoding _ascii; private bool _disposed = false; public Testing() { _ascii = new ASCIIEncoding(); } public int DoSomething(string message) { return _ascii.GetByteCount(message); } } 

当我点击button1时,我正在创建新的对象测试。 _d是对这个新对象的引用。 我正在使用JetBrains dotTrace Memory转储内存并看到这个新对象存在。 点击button2后我将boolean _first设置为true,以便_d变得无法访问。 此时我想当我运行GC.Collect()GC将从堆栈中“清除”此对象,但我发现它仍然存在。 我误解了GC的工作? 或者我这样做错了?
当我设置_d = null;时,它正在工作_d = null;

设置first=false不会使GC无法访问_d实例。 从逻辑上讲,您可能永远不会再次使用它,但它仍然在Form1类中引用。

如果有人再次设置first=true ,你会不期望该对象仍可用?

单击Button2不会使_d无法访问。

GC仅收集未被root对象引用的对象。
只要您的表单引用_d ,就不会收集它。

这是因为_d是对您设置且从不清除的Testing实例的引用。 _d仍然指向堆上的对象,并将保持此引用,直到您清除它(通过调用( _d = null )。

无法访问并不意味着_d不能分配给其他东西,而是坐在堆中的对象不可能被再次调用(因为代码中不存在引用)

因此GC无法清除它,因为它可能仍会在您的代码中稍后使用。

您误解了GC如何确定可以访问的对象:当前本地范围中的变量引用的任何对象,任何静态变量以及可访问的对象的任何实例变量本身都是“可访问的” – 将其视为一个图,前面提到的变量是图的“根”。

在您的示例中, _d仍然保持对对象的引用,因此它仍然可以访问,并且不会被垃圾回收。

如果你要调用GC.Collect(),所有对象,无论它们在内存中的时间长短,都会被考虑收集; 但是,GC不会收集托管代码中引用的对象。 检查一下