Lets say we have following sample code in C#:
class BaseClass
  {
    public virtual void HelloWorld()
    {
      Console.WriteLine("Hello Tarik");
    }
  }
  class DerivedClass : BaseClass
  {
    public override void HelloWorld()
    {
      base.HelloWorld();
    }
  }
  class Program
  {
    static void Main(string[] args)
    {
      DerivedClass derived = new DerivedClass();
      derived.HelloWorld();
    }
  }
When I ildasmed the following code:
.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       15 (0xf)
  .maxstack  1
  .locals init ([0] class EnumReflection.DerivedClass derived)
  IL_0000:  nop
  IL_0001:  newobj     instance void EnumReflection.DerivedClass::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  callvirt   instance void EnumReflection.BaseClass::HelloWorld()
  IL_000d:  nop
  IL_000e:  ret
} // end of method Program::Main
However, csc.exe converted derived.HelloWorld(); --> callvirt   instance void EnumReflection.BaseClass::HelloWorld(). Why is that? I didn't mention BaseClass anywhere in the Main method.
And also if it is calling BaseClass::HelloWorld() then I would expect call instead of callvirt since it looks direct calling to BaseClass::HelloWorld() method.