using System;

namespace Example
{
    public class Test1 
    {
        public string strMyValue;
//        public Test1()
//        {
//            Console.WriteLine("Test1 () Constructor");
//            strMyValue = "Doh!";
//        }
        public Test1(string inMyValue)
        {
            Console.WriteLine("    Test1 ({0}) Constructor", inMyValue);
            strMyValue = inMyValue;
        }
        ~Test1()
        {
            Console.WriteLine("    Test1 Finalize [{0}]", strMyValue);
        }
    }

    public class Test2 : Test1
    {
        //protected override void Finalize() 
        //
        //I tried the above line and got a compiler error CS0249 
        //  because ~Test2 is the required Finalize format for C#
        //  from the MSDN site:
        //
        //  ~MyClass()
        //  {
        //     // Perform some cleanup operations here.
        //  }
        //
        //  This code implicitly translates to the following.
        //  
        //  protected override void Finalize()
        //  {
        //     try
        //     {
        //        // Perform some cleanup operations here.
        //     }
        //     finally
        //     {
        //        base.Finalize();
        //     }
        //  }
        public Test2(string x) 
            : base(x)   // If you omit this line it will not compile
                        // unless you add a constructor for Test1 which
                        // takes no arguments.  I have provided one, comment the 
                        // base call out and then uncomment the Test1() above
                        // and take a look...I can wait...ok, see how it
                        // creates an underlying Type1 for the Test2?  I didn't
                        // expect that.
        {
            Console.WriteLine("    Test2 ({0}) Constructor", x);
        }
        ~Test2()
        {
            Console.WriteLine("    Test2 Finalize [{0}]", strMyValue);
        }
    }

    public struct Test3
    {
        public string strMyValue;
        public Test3(string inMyValue)
        {
            strMyValue = inMyValue;
        }
        //protected override void Finalize()
        //see the note above
        //
        //but I still can't do the following because this isn't a class
        //  ~Test3()
        //  {
        //      Console.WriteLine("Test3 Finalize [{0}]", strMyValue);
        //  }
    }

    public class MemoryExample
    {
        static public object objHolder;  // defaults to null

        static void Main(string[] args)
        {
            object one;
            
            Console.WriteLine("BEGIN:");
            Console.WriteLine("  Create a new Test1");
            one = new Test1("blah");
            Console.WriteLine("  Create a new Test2");
            one = new Test2("foo");
            Console.WriteLine("  Create a new Test3");
            one = new Test3("barh");
            one = null;
            Console.WriteLine("  Start First Collection Point");
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Console.WriteLine("  End First Collection Point");
            Console.WriteLine("END");
        }
    }

}