Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Memory allocation/de-allocation question regarding scope

I was recently going through a garbage collection article and decided to play along and attempt to gain a greater understanding. I coded the following, playing around with the using statement, but was surprised with the results... I expected e.Parent.Name outside of the using block to go ka-blooey.

What exactly is going on here?

static void Main(string[] args)
        {
            Employee e = new Employee();

            using (Parent p = new Parent())
            {
                p.Name = "Betsy";
                e.Parent = p;
                Console.WriteLine(e.Parent.Name);
            }

            Console.WriteLine(e.Parent.Name);            

            Console.ReadLine();
        }

        public class Employee
        {
            public Parent Parent;
        }

        public class Parent : IDisposable
        {
            public string Name;

            public void Dispose()
            {
                Console.WriteLine("Disposing Parent");
            }
        }
like image 210
Mike M. Avatar asked Aug 10 '10 21:08

Mike M.


1 Answers

Your Dispose method doesn't actually do anything to the instance of Parent, hence it's still fair game / works as a usable instance of a class.

IDisposable is usually used when your class holds onto an unmanaged resource, such as a database connection or a file, so that it can be cleaned up when Dispose() is called. Just calling Dispose doesn't do anything to the unmanaged resources, there has to be some code in the method that does something to those resources. Whilst c# might have the using() {} syntax to wrap instantiation and disposal of an IDisposable object in a try/catch/finally, it doesn't mean it does anything "special" with the disposed object.

Imagine, hypothetically, that Name is actually an unmanaged resource, rather than just a string, your Dispose() method could read:

public void Dispose()
{
    Name = null;
    Console.WriteLine("Disposing Parent");
}

Because you've assigned p to e.Parent, the object itself is still "in scope" as there's a reference to it, hence it's still accessible for Console.WriteLine(e.Parent.Name); to produce output from.

It's also currently "CLR Week" over at The Old New Thing and the first 3 articles of the week are discussing the Garbage Collector and how it works/behaves. They're well worth a read:

  • Everybody thinks about garbage collection the wrong way
  • When does an object become available for garbage collection?
  • Everybody thinks about CLR objects the wrong way (well not everybody)
like image 184
Rob Avatar answered Oct 15 '22 05:10

Rob