Как callvirt работает под капотом?

Я пытаюсь понять, как CLR реализует ссылочные типы и полиморфизм. Я сослался на Essential .Net Vol 1 Дона Бокса, который очень помогает восполнить большую часть материала. Но я застрял / смущен следующей проблемой, когда попытался поиграть с некоторым кодом IL, чтобы лучше понять.

Я постараюсь объяснить проблему как можно лучше. Рассмотрим следующий код

class Base
{
    public void m()
    {
        Console.WriteLine("Base.m");
    }
}
class Derived : Base
{
    public void m()
    {
        Console.WriteLine("Derived.m");
    }
}

. Теперь рассмотрим простое консольное приложение с IL основного метода, показанного ниже. Я вручную настроил IL, созданный компилятором, чтобы понять и снова собрать его с помощью ILAsm.exe

.class private auto ansi beforefieldinit Console1.Program
       extends [mscorlib]System.Object
{
    .method private hidebysig static void  Main(string[] args) cil managed
    {
      .entrypoint
      // Code size       44 (0x2c)
      .maxstack  1
      .locals init ([0] class Console1.Base d)
      nop
      newobj     instance void Console1.Base::.ctor()
      stloc.0
      ldloc.0
      callvirt   instance void Console1.Derived::m()
      nop
      call       string [mscorlib]System.Console::ReadLine()
      pop
      ret
    } // end of method Program::Main
} // end of class Console1.Program

. Я ожидал, что этот код НЕ запустится, поскольку ссылка на объект указывает на объект Base, и нет возможности таблица методов базового объекта будет иметь запись для метода m (), определенного в классе Derived.

Но волшебным образом этот код выполняет Derived.m () !!

Итак, есть два вопроса, которые я не задаю. Я понимаю в приведенном выше коде:

  1. Какое значение имеет Тип, указанный в приведенном ниже коде IL? Я попытался поэкспериментировать, изменив это на разные типы (например, System.Exception !!), и никаких ошибок не сообщалось. Почему ??

    .locals init ([0] класс Console1.Base d)

  2. Как именно работает callvirt? Как вызов был перенаправлен на Derived.m ()?

Заранее спасибо !!

С уважением, Ajay

5
задан ajay 27 November 2010 в 15:39
поделиться