Я заметил, что в 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 в соответствии с общими параметрами, а затем вызывает его. Кто-нибудь писал о специфике этой реализации? Насколько хорошо он работает по сравнению с неуниверсальным случаем?