直接调用委托、使用 DynamicInvoke 和使用 DynamicInvokeImpl 有什么区别? [英] What is the difference between calling a delegate directly, using DynamicInvoke, and using DynamicInvokeImpl?

查看:50
本文介绍了直接调用委托、使用 DynamicInvoke 和使用 DynamicInvokeImpl 有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

DynamicInvoke 和 DynamicInvokeImpl 的文档说:

The docs for both DynamicInvoke and DynamicInvokeImpl say:

动态调用(后期绑定)当前所代表的方法委托.

Dynamically invokes (late-bound) the method represented by the current delegate.

我注意到 DynamicInvoke 和 DynamicInvokeImpl 采用对象数组而不是特定的参数列表(这是我猜测的后期绑定部分).但这是唯一的区别吗?DynamicInvoke和DynamicInvokeImpl有什么区别.

I notice that DynamicInvoke and DynamicInvokeImpl take an array of objects instead of a specific list of arguments (which is the late-bound part I'm guessing). But is that the only difference? And what is the difference between DynamicInvoke and DynamicInvokeImpl.

推荐答案

直接调用(Invoke(...)的简写)和使用的主要区别DynamicInvoke 是性能;根据我的衡量,超过 *700 倍(下图).

The main difference between calling it directly (which is short-hand for Invoke(...)) and using DynamicInvoke is performance; a factor of more than *700 by my measure (below).

使用直接/Invoke 方法,参数已经通过方法签名进行了预验证,并且已经存在将这些参数直接传递给方法的代码(我会说作为 IL",但我似乎记得运行时直接提供了这个,没有任何 IL).使用 DynamicInvoke 它需要通过反射从数组中检查它们(即它们是否都适合此调用;它们是否需要拆箱等);这是(如果您在紧密循环中使用它),应尽可能避免.

With the direct/Invoke approach, the arguments are already pre-validated via the method signature, and the code already exists to pass those into the method directly (I would say "as IL", but I seem to recall that the runtime provides this directly, without any IL). With DynamicInvoke it needs to check them from the array via reflection (i.e. are they all appropriate for this call; do they need unboxing, etc); this is slow (if you are using it in a tight loop), and should be avoided where possible.

示例;结果优先(我增加了上一次编辑的 LOOP 计数,以便进行合理的比较):

Example; results first (I increased the LOOP count from the previous edit, to give a sensible comparison):

Direct: 53ms
Invoke: 53ms
DynamicInvoke (re-use args): 37728ms
DynamicInvoke (per-cal args): 39911ms

带代码:

static void DoesNothing(int a, string b, float? c) { }
static void Main() {
    Action<int, string, float?> method = DoesNothing;

    int a = 23;
    string b = "abc";
    float? c = null;
    const int LOOP = 5000000;

    Stopwatch watch = Stopwatch.StartNew();
    for (int i = 0; i < LOOP; i++) {
        method(a, b, c);
    }
    watch.Stop();
    Console.WriteLine("Direct: " + watch.ElapsedMilliseconds + "ms");

    watch = Stopwatch.StartNew();
    for (int i = 0; i < LOOP; i++) {
        method.Invoke(a, b, c);
    }
    watch.Stop();
    Console.WriteLine("Invoke: " + watch.ElapsedMilliseconds + "ms");

    object[] args = new object[] { a, b, c };
    watch = Stopwatch.StartNew();
    for (int i = 0; i < LOOP; i++) {
        method.DynamicInvoke(args);
    }
    watch.Stop();
    Console.WriteLine("DynamicInvoke (re-use args): "
         + watch.ElapsedMilliseconds + "ms");

    watch = Stopwatch.StartNew();
    for (int i = 0; i < LOOP; i++) {
        method.DynamicInvoke(a,b,c);
    }
    watch.Stop();
    Console.WriteLine("DynamicInvoke (per-cal args): "
         + watch.ElapsedMilliseconds + "ms");
}

这篇关于直接调用委托、使用 DynamicInvoke 和使用 DynamicInvokeImpl 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆