Réponses:
Lorsque vous avez une instance de délégué, vous pouvez connaître le type exact ou simplement savoir qu'il s'agit d'un fichier Delegate
. Si vous connaissez le type exact, vous pouvez utiliser Invoke
, ce qui est très rapide - tout est déjà pré-validé. Par exemple:
Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);
Toutefois! Si vous savez juste que c'est le cas Delegate
, il doit résoudre les paramètres, etc. manuellement - cela peut impliquer un déballage, etc. - beaucoup de réflexion est en cours. Par exemple:
Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);
Notez que j'ai écrit la args
longue main pour indiquer clairement qu'un object[]
est impliqué. Il y a beaucoup de coûts supplémentaires ici:
MethodInfo
En gros, évitez DynamicInvoke
quand vous le pouvez. Invoke
est toujours préférable, sauf si tout ce que vous avez est un Delegate
et un object[]
.
Pour une comparaison des performances, les éléments suivants en mode version en dehors du débogueur (un exe de console) s'impriment:
Invoke: 19ms
DynamicInvoke: 3813ms
Code:
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
. Pourquoi les comparez-vous plus d'un appel? Et pourquoi le premier prend plus de temps que le deuxième appel de fonction?