Я пытаюсь понять, как CLR реализует ссылочные типы и полиморфизм.Я сослался на Essential .Net Vol. 1 от Don Box, который помогает справиться с большинством вещей.Но я застрял / смутился из-за следующей проблемы, когда попытался поиграться с некоторым кодом 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
Я ожидал, что этот код NOT будет запущен, так как ссылка на объект указывает на объектBase, и нет способа, чтобы таблица методов базового объекта имела запись для метода m (), определенного в классе Derived.
Но волшебным образом этот код выполняет Derived.m () !!
Итак, в вышеприведенном коде есть два вопроса, которые я не понимаю:
Какое значение имеет тип, указанный в приведенном ниже коде IL?Я попытался поэкспериментировать, изменив это на различные типы (например, System.Exception !!), и об ошибках не сообщается.Почему ??
.locals init ([0] класс Console1.Base d)
- Как именно работает callvirt?Как звонок был перенаправлен на Derived.m ()?
Заранее спасибо !!
С уважением, Ajay