Garbage Collector C#, question about 'clearing' objects
I read some informations about Garbage Collection (how it's works etc.). I tried understand how it's working doing my examples but I think I have problem. I know Garbage Collector runs when:
is not enough memory, you call GC.Collect(). This is my code: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);
}
}
When I click button1 I'm creating new object Testing. _d is reference to this new object. I'm dumping memory using JetBrains dotTrace Memory and see this new object exists. After click button2 I'm setting boolean _first to true in order to _d became unreachable. At this point I thought when I run GC.Collect() GC will 'clear' this object from stack, but I see it's still exists. I misunderstood about GC work? or I'm doing this wrong?
It's working when I set_d = null;
Clicking Button2 does not make _d
unreachable.
The GC only collects objects that are not referenced by a rooted object.
As long as your form has a reference to _d
, it won't be collected.
Setting first=false
does not make the _d
instance unreachable in terms of the the GC. Logically you may never use it again but it is still referenced in the Form1
class.
If someone were to set first=true
again, would you not expect the object to still be usable?
This is because _d
is a reference to the Testing
instance which you set and never clear. _d
still points to the object on the heap and will maintain this reference until you clear it (by calling (_d = null
).
Unreachable doesn't mean that _d
cannot be assigned to something else, but rather the object sitting in the heap has no chance of being called again (as no references exist in the code)
Therefore the GC cannot possibly clear it, as it may be still used later on in your code.
You have misunderstood how the GC is determining an object to be reachable: Any object that is referenced by a variable in the current local scope, any static variables and any instance variables of objects that are reachable are themselves "reachable" - look at it as a graph with the fore-mentioned variables as "roots" of the graph.
In your example _d
is still holding a reference to your object so it is still reachable and won't be garbage collected.
If you were to call GC.Collect(), all objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected by GC. Check this
精彩评论