Это просто происходит со мной по одному вопросу о дизайне кода. Скажем, у меня есть один метод "шаблон", который вызывает некоторые функции, которые могут "меняться". Интуитивно понятный дизайн должен следовать "Шаблон дизайна шаблона". Определите функции изменения как "виртуальные" функции, которые будут переопределены в подклассах. Или я могу просто использовать функции делегата без "виртуального". Функции делегата вводятся так, что их можно настроить также.
Первоначально я думал, что второй способ "делегирования" будет быстрее, чем "виртуальный", но некоторые фрагменты кода доказывают, что это неверно.
В приведенном ниже коде первый метод DoSomething следует за шаблоном шаблона. Он вызывает виртуальный метод IsTokenChar. Второй метод DoSomthing не зависит от виртуальной функции. Вместо этого у него есть делегат пропуска. На моем компьютере первый DoSomthing всегда быстрее второго. Результат подобен 1645: 1780.
"Виртуальный вызов" является динамическим связыванием и должен быть более затратным по времени, чем прямой вызов делегирования, не так ли? но результат показывает, что это не так.
Кто-нибудь может это объяснить?
using System;
using System.Diagnostics;
class Foo
{
public virtual bool IsTokenChar(string word)
{
return String.IsNullOrEmpty(word);
}
// this is a template method
public int DoSomething(string word)
{
int trueCount = 0;
for (int i = 0; i < repeat; ++i)
{
if (IsTokenChar(word))
{
++trueCount;
}
}
return trueCount;
}
public int DoSomething(Predicate<string> predicator, string word)
{
int trueCount = 0;
for (int i = 0; i < repeat; ++i)
{
if (predicator(word))
{
++trueCount;
}
}
return trueCount;
}
private int repeat = 200000000;
}
class Program
{
static void Main(string[] args)
{
Foo f = new Foo();
{
Stopwatch sw = Stopwatch.StartNew();
f.DoSomething(null);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
{
Stopwatch sw = Stopwatch.StartNew();
f.DoSomething(str => String.IsNullOrEmpty(str), null);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
}
}