Antworten:
Wenn Sie eine Delegateninstanz haben, kennen Sie möglicherweise den genauen Typ oder wissen nur, dass es sich um eine handelt Delegate. Wenn Sie den genauen Typ kennen, können Sie ihn verwenden Invoke, was sehr schnell geht - alles ist bereits vorab validiert. Beispielsweise:
Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);
Jedoch! Wenn Sie nur wissen, dass Delegatedies der Fall ist, müssen die Parameter usw. manuell aufgelöst werden - dies kann das Auspacken usw. beinhalten - es wird viel nachgedacht. Beispielsweise:
Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);
Hinweis: Ich habe die argslange Hand geschrieben, um zu verdeutlichen, dass es sich um eine object[]handelt. Hier fallen viele zusätzliche Kosten an:
MethodInfoVermeiden DynamicInvokeSie grundsätzlich, wann immer Sie können. Invokeist immer vorzuziehen, es sei denn, Sie haben nur ein Delegateund einobject[] .
Für einen Leistungsvergleich wird im Release-Modus außerhalb des Debuggers (einer Konsolen-Exe) Folgendes gedruckt:
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. Warum vergleichen Sie sie mehr als 1 Anruf? Und warum dauert der erste länger als der zweite Funktionsaufruf?