0

I started creating a small testprogram to prove that the scope of abcTest is different from the lifetime of abcTest. While doing that I bumped into a problem that the Finalizer of ABC is called only after the main function completes. I thought it would get called on GC.Collect() since I set the object to null abc = null; in BCDs destructor. Please see the below code

namespace ConsoleApp1
{
    public class ABC
    {
        public void SaveReferenceToBCD(BCD bcdObj)
        {
            bcdObj.SetABCObject(this);
        }
        public void SayHello()
        {
            Console.WriteLine("\tHello from ABC");
        }
        ~ABC()
        {
            Console.WriteLine("\tDestructor of ABC");
        }
    }

    public class BCD
    {
        ABC abc = null;
        public void SetABCObject(ABC value)
        {
            abc = value;
        }
        public void SayHello()
        {
            abc.SayHello();
            Console.WriteLine("\tHello from BCD");
        }
        ~BCD()
        {
            abc = null;
            Console.WriteLine("\tDestructor of BCD");
        }
    }

    public class Workout
    {
        static void Main()
        {
            {
                BCD bcdTest = new BCD();
                {
                    ABC abcTest = new ABC();
                    abcTest.SaveReferenceToBCD(bcdTest);
                    // abcTest = null; 
                    /* If I uncomment the above line I get Output 2, 
                    * but I thought Output 1 should be same as Output 2, given that I set
                    * the value of "abc" to null in "BCD"s destructor */
                }

                Console.WriteLine("First GC Collect Start");
                GC.Collect();
                GC.WaitForPendingFinalizers();
                Console.WriteLine("First GC Collect END");

                bcdTest.SayHello();
                bcdTest = null;
            }
            Console.WriteLine("Second GC Collect Start");
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Console.WriteLine("Second GC Collect END");

            Console.WriteLine("Third GC Collect Start");
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Console.WriteLine("Third GC Collect END");
        }
    }
}

Output 1 Received: (with abcTest = null commented out)

First GC Collect Start
First GC Collect END
        Hello from ABC
        Hello from BCD
Second GC Collect Start
        Destructor of BCD
Second GC Collect END
Third GC Collect Start
Third GC Collect END

       Destructor of ABC (Printed only after the main function finishes its execution)

Output 2 Received: (with abcTest = null NOT commented out)

First GC Collect Start
First GC Collect END
        Hello from ABC
        Hello from BCD
Second GC Collect Start
        Destructor of ABC
        Destructor of BCD
Second GC Collect END
Third GC Collect Start
Third GC Collect END

I expected the Output 1 to have Destructor of ABC as well (similar to Output 2), given that I set the value of "abc" to null in "BCD"s destructor itself. Please help. Thanks!

Titus
  • 907
  • 8
  • 18
  • 1
    I'd hesitate to concern myself with the order in which objects are finalised but ... Debug or Release? If I recall the former retains references to objects for ... debugging ... until the end of the function's scope. – ta.speot.is Mar 18 '20 at 11:32
  • That's awesome!. Release build was the answer!. Thank you very much! – Titus Mar 18 '20 at 11:53

0 Answers0