Invoke和DynamicInvoke之间的区别

时间:2012-10-12 11:44:07

标签: c# .net delegates invoke dynamic-invoke

委托中的Invoke和DynamicInvoke有什么区别?请给我一些代码示例来解释这两种方法之间的区别。

1 个答案:

答案 0 :(得分:189)

当您拥有委托实例时,您可能知道确切的类型,或者您可能只知道它是Delegate。如果您知道确切的类型,则可以使用Invoke非常快 - 所有内容都已经过预先验证。例如:

Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);

然而!如果你只知道它是Delegate,它必须手动解决参数等 - 这可能涉及拆箱等 - 很多反思正在进行中。例如:

Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);

注意我已经写了args长手,以明确涉及object[]。这里有很多额外的费用:

  • 数组
  • 验证传递的参数是实际MethodInfo
  • 的“适合”
  • 必要时取消装箱等
  • 反射调用
  • 然后调用者需要做一些事情来处理返回值

基本上,尽可能避免DynamicInvokeInvoke始终是首选,除非您拥有Delegateobject[]

对于性能比较,调试器外部的发布模式(控制台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);