问题描述
||
我阅读了有关垃圾收集的一些信息(它的工作方式等)。我试图了解示例的工作方式,但是我认为我有问题。我知道垃圾收集器在以下情况下运行:
内存不足,
您调用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之后,我将布尔值_first设置为true,以使_d变得不可访问。在这一点上,我认为当我运行GC.Collect()时,GC会从堆栈中“清除”该对象,但我仍然看到它仍然存在。我对GC工作误解了吗?还是我做错了吗?
设置set1ѭ就可以了
解决方法
就GC而言,设置
first=false
不会使_d
实例不可访问。从逻辑上讲,您可能永远不会再使用它,但仍在Form1
类中引用了它。
如果有人再次设置first=true
,您是否不希望该对象仍然可用?
, 单击Button2不会使“ 3”无法访问。
GC仅收集没有被根对象引用的对象。
只要您的表格中引用了_d
,就不会收集该表格。
, 这是因为“ 3”是对您设置且永不清除的“ 9”实例的引用。 _d
仍指向堆上的对象,并且将维持此引用,直到您清除它为止(通过调用(_d = null
)。
不可达并不意味着不能将ѭ3分配给其他对象,而是堆中的对象没有机会再次被调用(因为代码中不存在引用)
因此,GC无法清除它,因为它可能在以后的代码中仍在使用。
, 您误解了GC如何确定可访问对象:当前本地范围中的变量引用的任何对象,可访问对象的任何静态变量和任何实例变量本身都是“可访问”-它作为图,其中前面提到的变量为图的“根”。
在您的示例中,“ 3”仍然保留着对您对象的引用,因此它仍然可以访问并且不会被垃圾回收。
, 如果要调用GC.Collect(),则将考虑所有对象(无论它们在内存中已经存放了多长时间);但是,GC不会收集托管代码中引用的对象。检查一下