I have come across something strange when writing unit-tests where I want to test that object can really be garbage collected (cause all events are clean up properly).
To have a minimal example I created a console project in visual-studio 2013 (Target Framework: 4.5.1) with the following code:
using System;
namespace GarbageCollectionFinalizerForLoop
{
class TestObj
{
~TestObj()
{
Program.DestructorWasCalled = true;
}
}
class Program
{
public static bool DestructorWasCalled = false;
static void Main(string[] args)
{
object myTestObj = new TestObj();
myTestObj = new object();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForFullGCComplete();
GC.Collect();
for (int i = 0; i < 1; i++)
{
}
Console.WriteLine("Finalizer was called: " + DestructorWasCalled);
Console.ReadLine();
}
}
}
It turns that the finalizer of the TestObj is not called when there is this useless for-loop. When the for-loop is commented out the destructor is called. So the for-loop seems to prevent that the garbage collector can collect this instance of TestObj. Multiple test yield the same result and this behavior seem 100% deterministic.
Then I switched the Target Framework to 3.5 and all of a sudden it worked as expected (the destructor function got called). Then I changed the Target Framework back to 4.5.1 and it still worked.
I was puzzled and tried project clean/rebuild/deleting file but I could not get back the old behavior. But when I created again a new project with the identical code I get back the buggy behavior... So it seems that switching to Target Framework 3.5 made the code run as expected even if you later switch back to 4.5.1. This is really strange to me.
I tried some more things (in parentheses the console output):
create project with 4.5.1 (FALSE), switch to 4.5 (FALSE), switch to 4.5.1 (FALSE)
create project with 4.5.1 (FALSE), switch to 4 (TRUE), switch to 4.5.1 (TRUE)
create project with 4.5.1 (FALSE), switch to 3.5 (TRUE), switch to 4.5.1 (TRUE)
create project with 4.5.1 (FALSE), switch to 3 (TRUE), switch to 4.5.1 (TRUE)
create project with 4.5.1 (FALSE), switch to 2 (TRUE), switch to 4.5.1 (TRUE)
Something strange is happening here. Does anybody have more information on this issue?
EDIT:
The behavior was the same for DEBUG and RELEASE builds and the "problem" only affects DEBUG build and RELEASE builds run from withing visual-studio.