views:

347

answers:

2

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
    } }
+3  A: 

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.

Lucero
That's not the reason. The reference isn't thrown away, it's considered inactive, and that has nothing at all to do with optimization. It's the other way around; the variable can be optimized away from that point as it's inactive.
Guffa
"Thrown away" may be a bit too simple as explanation, agreed. Still, the reason is correct; there is no strong reference kept in release mode which prevent the GC from collecting the instance.
Lucero
Because of optimizations in release mode, the reference scope is only valid till its last usage and not the entire block of code it is defined in. What happens in debug mode is clearly stated by Lucero above.
MSIL
+1  A: 

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.

Guffa