Я использую как С++, так и С#, и что-то, что было на мой взгляд, заключается в том, можно ли использовать generics в С# для вызова виртуальных функций на интерфейсах. Рассмотрим следующее:
int Foo1(IList<int> list)
{
int sum = 0;
for(int i = 0; i < list.Count; ++i)
sum += list[i];
return sum;
}
int Foo2<T>(T list) where T : IList<int>
{
int sum = 0;
for(int i = 0; i < list.Count; ++i)
sum += list[i];
return sum;
}
/*...*/
var l = new List<int>();
Foo1(l);
Foo2(l);
Внутри Foo1 каждый доступ к списку. Состав и список [i] вызывает вызов виртуальной функции. Если это были С++ с использованием шаблонов, то в вызове Foo2 компилятор смог бы увидеть, что вызов виртуальной функции можно отбросить и вставить, потому что конкретный тип известен во время создания шаблона.
Но что же касается С# и дженериков? Когда вы вызываете Foo2 (l), во время компиляции известно, что T является списком, и поэтому список list.Count и list [i] не должны включать вызовы виртуальных функций. Прежде всего, это была бы правильная оптимизация, которая не ужасно что-то сломала? И если да, то компилятор /JIT достаточно умный, чтобы сделать эту оптимизацию?