Выполнение полиморфизма метода C # с генериками - PullRequest
7 голосов
/ 25 мая 2010

Я заметил, что в C #, в отличие от C ++, вы можете комбинировать виртуальные и универсальные методы. Например:

using System.Diagnostics;

class Base {
    public virtual void Concrete() {Debug.WriteLine("base concrete");}
    public virtual void Generic<T>() {Debug.WriteLine("base generic");}
}

class Derived : Base {
    public override void Concrete() {Debug.WriteLine("derived concrete");}
    public override void Generic<T>() {Debug.WriteLine("derived generic");}
}

class App {
    static void Main() {
        Base x = new Derived();
        x.Concrete();
        x.Generic<PerformanceCounter>();
    }
}

Учитывая, что может быть создано любое количество версий Generic<T>, не похоже, что стандартный подход vtbl может использоваться для разрешения вызовов методов, и на самом деле это не так. Вот сгенерированный код:

        x.Concrete();
mov         ecx,dword ptr [ebp-8] 
mov         eax,dword ptr [ecx] 
call        dword ptr [eax+38h] 
        x.Generic<PerformanceCounter>();
push        989A38h 
mov         ecx,dword ptr [ebp-8] 
mov         edx,989914h 
call        76A874F1 
mov         dword ptr [ebp-4],eax 
mov         ecx,dword ptr [ebp-8] 
call        dword ptr [ebp-4] 

Дополнительный код, похоже, ищет динамический vtbl в соответствии с общими параметрами, а затем вызывает его. Кто-нибудь писал о специфике этой реализации? Насколько хорошо он работает по сравнению с неуниверсальным случаем?

Ответы [ 2 ]

5 голосов
/ 25 мая 2010

Реализация .NET generics может справиться с таким сценарием легко и с очень хорошей производительностью. Я написал сообщение в блоге об этом некоторое время назад.

Один из лучших ресурсов для поиска информации о том, как CLR реализует дженерики, - это бумага от Micosoft Research.

Вы правильно поняли vtable. То, как CLR создает исполняемый код для универсального типа, когда JIT-компилятор наталкивается на него, зависит от параметра универсального типа. Обработка отличается для типов значений и ссылочных типов.

В то время как исполняемый код (создание экземпляра, собственное изображение) совместно используется экземплярами для всех параметров универсального типа, которые являются ссылочными типами, виртуальная таблица, связанная с экземпляром (объектом) создания экземпляра, уникальна для конкретного типа параметра.

Вот соответствующая цитата из вышеупомянутой статьи:

4.2 Представление объектов Объекты в куче CLR, собираемой мусором, представлен указателем vtable с последующим содержимым объекта (например, поля или элементы массива). Главная роль vtable - это виртуальный метод рассылка: содержит указатель кода для каждого метода, который определен или наследуется классом объекта. Но для простых типов классов, по крайней мере, где есть один-к-одному соответствие между таблицами и классы, это также может быть использовано для представляют тип объекта. Когда Vtable используется таким образом, мы называем это дескриптор типа. В реализация полиморфизма на основе по полной специализации, понятие точного типа во время выполнения поставляется бесплатно как разные экземпляры один и тот же параметризованный тип имеет разные виртуальные таблицы. Но теперь предположим, что код разделены между различными такие как List<string> и List<object>. Vtables для два экземпляра будут идентичны, поэтому нам нужен какой-то способ представления инстанцирование во время выполнения.

...

[Для каждого экземпляра мы] Заменим указатель vtable указателем на объединенный и-экземпляр структуры и дублировать ее [структуру] в каждом экземпляре.

0 голосов
/ 25 мая 2010

Способ реализации обобщений .NET: для каждого использования универсального класса (или метода) CLR создает новую реализацию этого класса (или метода) с заполненным универсальным параметром. Для ссылочных типов все они совместно используют. единственная реализация (так как они все просто указатели одного размера); каждая структура имеет свою реализацию, так как все размеры разные.

Так что я предполагаю, что каждая реализация универсального типа / метода также имеет свой собственный vtable, и этот код выполняет «универсальную реализацию поиска», а затем «переопределение поиска виртуальной таблицы» в найденной реализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...