A Tricky Interview Question about C#

Here is a tricky interview question:

Please write output of following code and explain why?

class Base : IDisposable
{
   public Base()
   {
       Console.WriteLine(" Base Constructor");
   }
   static Base()
   {
       Console.WriteLine(" Base Static Constructor");
   }
   public void Dispose()
   {
       Console.WriteLine(" Base Dispose");
   }
   ~Base()
   {
       Console.WriteLine(" Base Destructor");
   }
}
class Derived : Base, IDisposable
{
   public Derived()
   {
       Console.WriteLine(" Derived Constructor");
   }
   static Derived()
   {
       Console.WriteLine(" Derived Static Constructor");
   }
   ~Derived()
   {
       Console.WriteLine(" Derived Destructor");
   }
   void IDisposable.Dispose()
   {
       Console.WriteLine(" Derived Dispose");
   }
}
class Program
{
   static void Main(string[] args)
   {
       Console.WriteLine("Start");
       using (Base test = new Derived())
       {
           Console.WriteLine(" Using test");
       }
       Console.WriteLine("End");
   }
}

The question is a bit hard for me and is confusing. I run it in console, and the result is:

C:\>test
Start
Derived Static Constructor
Base Static Constructor
Base Constructor
Derived Constructor
Using test
Derived Dispose
End

Derived Destructor
Base Destructor

C:\>

There are two processes in this question: constructing and destructing/garbage collection.

1. Constructing

The static constructor is quite tricky, just checked MSDN:  static constructor is called automatically to initialize the class before the first instance is created. My understanding is that before you begin the USE a class (instantiate a class or reference a static property/method in the class), the static constructor will be called automatically. So in the case, firstly we need to instantiate a Derived class, so the derived static constructor is called. Then run the derived constructor, and it will link to base constructor. So the base constructor will run before the derived one. Since we want to run the base constructor, the base static constructor will be called automatically. Then the base constructor will be called and then the derived constructor. So the order of constructing process will be:

Start
Derived Static Constructor
Base Static Constructor
Base Constructor
Derived Constructor

2. Destructing

Since we use Using statement to free the resources, so the Dispose method will be called immediately after the close brace in the derived class. So the result will be then:

Using test
Derived Dispose
End

The destructor will be called only by GC automatically. When the program ends, the destructor will be called by GC in CLR, and the derived class’s destructor will  be called before the base class’s. Here is the result after the above:

Derived Destructor
Base Destructor

When to use IDisposable or a desctructor

Firstly we should sort out what are managed resources and unmanaged resources.

  • Managed resources are those under the control of the Common Language Runtime (CLR), the runtime environment that executes C# programs.
  • Unmanaged resources are those outside of the control of the CLR. Unmanaged resources include such things as handles to windows, files, pens, brushes, and other objects the program is manipulating through API calls.

The following list summarizes the resource management rules and concepts:

  • If a class contains no managed resources and no unmanaged resources, it doesn’t need to implement IDisposable or have a destructor.
  • If the class has only managed resources, it should implement IDisposable but it doesn’t need a destructor. (When the destructor executes, you can’t be sure managed objects still exist, so you can’t call their Dispose methods anyway.)
  • If the class has only unmanaged resources, it needs to implement IDisposable and needs a destructor in case the program doesn’t call Dispose.
  • The Dispose method must be safe to run more than once. You can achieve that by using a variable to keep track of whether it has been run before.
  • The Dispose method should free both managed and unmanaged resources.
  • The destructor should free only unmanaged resources. (When the destructor executes, you can’t be sure managed objects still exist, so you can’t call their Dispose methods anyway.)
  • After freeing resources, the destructor should call GC.SuppressFinalize, so the object can skip the finalization queue.

4 comments

  1. table says:

    Hello, just wanted to mention, I lovеd this blog post.
    It was funny. Keep ⲟn pߋstіng!

  2. MartinNek says:

    Hi All im newbie here. Good article! Thx! Thx!

  3. Incredible! This blog looks just like my old one! It’s on a completely different topic but it has pretty much the same page layout and design. Outstanding choice of colors!

  4. Senaida says:

    Great post! We are linking to this particularly great article on our website.
    Keep up the good writing.

Leave a Reply

Your email address will not be published. Required fields are marked *