Let’s consider this code for a moment:

   1:  public abstract class Animal { } 
   3:  public class Tiger : Animal { } 
   5:  public class Elephant : Animal { } 
   7:  public class MyClass 
   8:  { 
   9:      public static void Main() 
  10:      { 
  11:          Animal a = new Tiger();  
  12:      } 
  13:  }

Now answer these two questions:

  • What is the compile time type of the variable a?
  • What is the runtime time of the variable a?

If your answer is:

Compile time type is Animal and runtime type is Tiger then you are right on the money!

Why is that?

Because, for the compiler, the type of the variable is the type you used to define it. In this case, your variable is defined as type Animal, which means that the compile time type of it is Animal.

However, you are assigning to that variable a new instance of type Tiger. This means that, when you are running the program, a memory location will be created to store a variable of type Tiger. Also, if you look at the definition for type Animal, you can see that the type is declared as Abstract and an abstract type cannot be instantiated.

Why is this important? Well, in C# 4.0, the Runtime Binder that we introduced uses the runtime type of variables instead of the compile time type when doing overload resolution.