Respuestas:
Cuando tiene una instancia de delegado, puede saber el tipo exacto, o simplemente puede saber que es un Delegate
. Si conoce el tipo exacto, puede usarlo Invoke
, que es muy rápido : todo ya está prevalidado. Por ejemplo:
Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);
¡Sin embargo! Si solo sabe que es así Delegate
, tiene que resolver los parámetros, etc. manualmente, esto puede implicar unboxing, etc., se está produciendo mucha reflexión. Por ejemplo:
Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);
Tenga en cuenta que he escrito la args
letra larga para dejar en claro que un object[]
está involucrado. Aquí hay muchos costos adicionales:
MethodInfo
Básicamente, evite DynamicInvoke
siempre que pueda. Invoke
siempre es preferible, a menos que todo lo que tenga sea un Delegate
y un object[]
.
Para una comparación de rendimiento, se imprime lo siguiente en modo de lanzamiento fuera del depurador (un exe de consola):
Invoke: 19ms
DynamicInvoke: 3813ms
Código:
Func<int,int> twice = x => x * 2;
const int LOOP = 5000000; // 5M
var watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
twice.Invoke(3);
}
watch.Stop();
Console.WriteLine("Invoke: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
twice.DynamicInvoke(3);
}
watch.Stop();
Console.WriteLine("DynamicInvoke: {0}ms", watch.ElapsedMilliseconds);
Invoke: 0,0478ms, DynamicInvoke: 0,053ms
. ¿Por qué los estás comparando más de 1 llamada? ¿Y por qué la primera tarda más que la segunda llamada de función?