Me acaba de ocurrir una cuestión de diseño de código. Diga, tengo un método de "plantilla" que invoca algunas funciones que pueden "alterar". Un diseño intuitivo es seguir "Patrón de diseño de plantilla". Defina que las funciones de alteración sean funciones "virtuales" que se anularán en subclases. O bien, puedo usar funciones de delegado sin "virtual". Las funciones delegadas se inyectan para que también se puedan personalizar.C#: ¿La invocación de funciones virtuales es incluso más rápida que una invocación de delegado?
Originalmente, pensé que el segundo modo de "delegado" sería más rápido que el modo "virtual", pero algunos fragmentos de código prueban que no es correcto.
En el siguiente código, el primer método DoSomething sigue "patrón de plantilla". Llama al método virtual IsTokenChar. El segundo método DoSomthing no depende de la función virtual. En cambio, tiene un delegado de transferencia. En mi computadora, el primer DoSomthing siempre es más rápido que el segundo. El resultado es como 1645: 1780.
"Invocación virtual" es un enlace dinámico y debería costar más tiempo que la invocación de delegación directa, ¿verdad? pero el resultado muestra que no lo es.
¿Alguien puede explicar esto?
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);
}
}
}
Uno de Jon Skeet, me siento! ;) –
@Mitch: en realidad no había visto tu comentario antes de responder, pero me siento halagado :) –
Por cierto, la diferencia es que me siento más marcado con una compilación optimizada –