首页 文章

Invoke和DynamicInvoke之间的区别

提问于
浏览
114

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

1 回答

  • 176

    当你有一个委托实例时,你可能知道确切的类型,或者你可能只知道它是 Delegate . 如果你知道确切的类型,你可以使用 Invoke ,这是 very fast - 一切都已预先验证 . 例如:

    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 的"fit"
      根据需要

    • 取消装箱等

    • reflection-invoke

    • 然后调用者需要做一些事情来处理返回值

    基本上,尽可能避免 DynamicInvoke . Invoke 总是可取的,除非你拥有的只是 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);
    

相关问题