I wanted to try how garbage collector works in .NET, but results are not clear for me.
public class Test
{
public string Name { get; set; }
~Test()
{
Console.WriteLine("NICE");
}
}
public class Program
{
public static void Main(string[] args)
{
Test instance = new Test()
{
Name = "Name"
};
instance = null;
GC.Collect(3);
GC.WaitForPendingFinalizers();
Console.WriteLine("FINISHED");
}
}
in this code Nice is not printed. I think that it should print NICE, because I created object called instance and then I changed it’s reference to null, which means that original reference now is in heap and there is not reference to it.
but then I wrote this code:
public class Test
{
public string Name { get; set; }
~Test()
{
Console.WriteLine("NICE");
}
}
public class Program
{
public static void Test()
{
Test x = new Test();
x = new Test();
x = new Test();
x = new Test();
}
public static void Main(string[] args)
{
Test();
GC.Collect(3);
GC.WaitForPendingFinalizers();
Console.WriteLine("FINISHED");
}
}
when I call Test() function, all 4 objects which was created in this function is finalized by garbage collector and NICE is printed 4 times.
can someone explain why first code does’t print ‘NICE’.
I think that I have wrong vision about garbage collector because of this behiaviour.
2
The fact that you see nothing is actually an interesting result of two things.
-
The JIT has autonomy to extend an object’s lifetime to the end of a scope.
This is why in your 2nd example, where the objects are declared in a different function, you see them get collected. Ref: This book was for earlier Framework versions, but looks like the behaviour hasn’t changed. -
Finalizers are not called at termination of program.
You may expect your finalizer – even if it’s not called by the GC – would still be called when the app terminates. There’s some discussion about it here (which also touches on point 1 above). But basically, no, it’s not guaranteed. Please don’t clean up resources in a finalizer, do it with a Dispose pattern instead.