Рассмотрим этот фрагмент IL (который был создан с помощью C# компилятор от Microsoft):Почему виртуальные элементы System.Object вызываются в unboxed типах значений (которые не имеют базового класса)?
.class public sequential ansi sealed beforefieldinit Foo
extends [mscorlib]System.ValueType
{ … }
.method private hidebysig static void Main(string[] args) cil managed
{
.maxstack 1
.locals init ([0] valuetype Foo foo)
ldloca.s foo // ?
constrained. Foo // ?
callvirt instance string [mscorlib]System.Object::ToString() // ?
pop
ret
}
Я хотел бы точно знать, что происходит в трех линиях отмечен // ?
: Как это возможно, что виртуальный метод (System.Object
ToString
) вызывается в unboxed тип значения, который (согласно разделу I.8.9.7 спецификации CLI) вообще не имеет базового типа?
Моего текущее, неполное понимание таково:
ldloca.s foo
приводит к транзиторному указателю (*
) к локальным переменнымfoo
(который содержит Unboxed значения типаvaluetype Foo
), который в этом случае, в соответствии с раздел I.12.3.2.1 спецификации CLI, может использоваться там, где ожидаются управляемые указатели (&
).Этот указатель
*
будет действовать как этот указатель для вызова метода. Это представляется законным, поскольку он может действовать как управляемый указатель (&
) здесь. В стандарте CLI упоминается эта возможность в разделе I.8.9.7.Префикс
constrained. Foo
для предотвращения боксаvaluetype Foo
значениеboxed Foo
объект.
Но остается основной вопрос: почему виртуальный метод может быть вызван на unboxed значение, которое не наследует этот виртуальный метод?
Если я правильно вас понимаю, то (3) применим в моем вопросе: Я вызываю 'foo.ToString()' (если вы разрешите мне это краткое использование синтаксиса C#). 'foo' имеет тип' valuetype Foo', который является типом значения и не реализует 'ToString' (потому что я сам не определил этот метод, и у' valuetype Foo' нет никакого базового типа, из которого он мог бы наследовать 'ToString '). Таким образом, в соответствии с тем, что вы говорите, значение в 'foo' помещается в квадрат в значение типа' boxed Foo', которое наследуется от 'System.ValueType', которое имеет реализацию' ToString'. Вы согласны? – stakx
@stakx: Упс, я неправильно читаю ваш пример. Я уточню свой ответ. –
@stakx: Да, ты подвел итог. –