Risposte:
Quando si dispone di un'istanza delegata, è possibile conoscere il tipo esatto oppure si può semplicemente sapere che si tratta di un Delegate
. Se conosci il tipo esatto, puoi usare Invoke
, che è molto veloce , tutto è già pre-validato. Per esempio:
Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);
Però! Se sai solo che lo è Delegate
, deve risolvere manualmente i parametri ecc. - Ciò potrebbe comportare unboxing, ecc. - Sta succedendo molta riflessione. Per esempio:
Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);
Nota ho scritto la args
mano lunga per chiarire che object[]
è coinvolto un. Ci sono molti costi extra qui:
MethodInfo
Fondamentalmente, evita DynamicInvoke
quando puoi. Invoke
è sempre preferibile, a meno che tutto ciò che hai sia a Delegate
e an object[]
.
Per un confronto delle prestazioni, viene stampato quanto segue in modalità di rilascio all'esterno del debugger (un exe console):
Invoke: 19ms
DynamicInvoke: 3813ms
Codice:
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
. Perché li stai confrontando più di 1 chiamata? E perché il primo impiega più tempo della seconda chiamata di funzione?