当你有一个委托实例,你可能知道确切的类型,或者你可能只是知道它是一个委托。如果你知道确切的类型,你可以使用Invoke,这是非常快 – 一切都已经过预先验证。例如:
Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);
然而!如果你只是知道它是委托,它必须手动解决参数等 – 这可能涉及拆箱等 – 大量的反思正在进行。例如:
Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);
注意我写了args长手,以表明一个对象[]涉及。这里有很多额外的费用:
>数组
>验证传递的参数是一个“适合”实际MethodInfo
>拆箱等
> reflection-invoke
>然后调用者需要做一些事情来处理返回值
基本上,避免DynamicInvoke时,你可以。 Invoke总是首选,除非你有一个Delegate和一个对象[]。
为了进行性能比较,在调试器之外的版本模式(控制台exe)中打印:
Invoke: 19ms
DynamicInvoke: 3813ms
码:
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);