Quelle est la différence entre Invoke et DynamicInvoke dans les délégués? S'il vous plaît, donnez-moi un exemple de code qui explique la différence entre ces deux méthodes.
Lorsque vous avez une instance de délégué, vous pouvez connaître le type exact ou simplement vous assurer qu'il s'agit d'un 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 simplement que c'est Delegate
, il doit résoudre les paramètres, etc. manuellement - cela peut impliquer unboxing, 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 main args
longue pour indiquer clairement qu'un object[]
est impliqué. Il y a beaucoup de coûts supplémentaires ici:
MethodInfo
En gros, évitez DynamicInvoke
chaque fois que vous le pouvez. Invoke
est toujours préférable, à moins que tout ce que vous avez est un Delegate
et un object[]
.
Pour une comparaison des performances, les éléments suivants en mode publication en dehors du débogueur (un fichier exe de la console) sont imprimés:
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);