I am running the code below and the result is totally different when it runs in Release mode. While in Debug mode, it never collects the object of class A and in Reaelse mode it immediately collects the object of class A.
Can someone explain why.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2 {
class Program
{
static void Main(string[] args)
{
A obj = new A();
B bobj = obj.objB;
GC.Collect();
GC.WaitForPendingFinalizers();
while (bobj.isLive)
{
Console.WriteLine("Is Alive!!");
}
Console.WriteLine("Is Dead!!");
Console.ReadLine();
}
}
class A:IDisposable
{
public B objB = new B();
public A()
{ }
~A()
{
objB.Dispose();
}
#region IDisposable Members
public void Dispose()
{
GC.SuppressFinalize(this);
}
#endregion
}
class B:IDisposable
{
public bool isLive = true;
#region IDisposable Members
public void Dispose()
{
this.isLive = false;
GC.SuppressFinalize(this);
}
#endregion
} }
The garbage collector handles variable usage differently in debug mode and release mode.
In release mode the usage of a variable is only where it's actually used. After the last use of the varaible, the object is up for garbage collection.
In debug mode the usage of a varaible is expanded to it's scope. The reason for this is so that the watch window in the debugger can show the value of a variables throughout it's scope.
In Debug mode, the compiler does not optimize the local variables. Therefore, the reference to A still exists. In Release mode, the compiler optimized the usage so that the reference is thrown away and the object can be collected.
I just found this behavior in my tests. Inserting
right before GC.Collect() should help. I think that is kind of "simulated" optimization.