委托中的Invoke和DynamicInvoke有什么区别?请给我一些代码示例来解释这两种方法之间的区别 .
当你有一个委托实例时,你可能知道确切的类型,或者你可能只知道它是 Delegate . 如果你知道确切的类型,你可以使用 Invoke ,这是 very fast - 一切都已预先验证 . 例如:
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[] . 这里有很多额外的费用:
args
object[]
数组
验证传递的参数是实际 MethodInfo 的"fit"根据需要
MethodInfo
取消装箱等
reflection-invoke
然后调用者需要做一些事情来处理返回值
基本上,尽可能避免 DynamicInvoke . Invoke 总是可取的,除非你拥有的只是 Delegate 和 object[] .
DynamicInvoke
对于性能比较,调试器外部的发布模式(控制台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);
1 回答
当你有一个委托实例时,你可能知道确切的类型,或者你可能只知道它是
Delegate
. 如果你知道确切的类型,你可以使用Invoke
,这是 very fast - 一切都已预先验证 . 例如:然而!如果你只知道它是
Delegate
,它必须手动解决参数等 - 这可能涉及拆箱等 - 很多反思正在进行中 . 例如:注意我已经写了
args
长手,以明确涉及object[]
. 这里有很多额外的费用:数组
验证传递的参数是实际
MethodInfo
的"fit"根据需要
取消装箱等
reflection-invoke
然后调用者需要做一些事情来处理返回值
基本上,尽可能避免
DynamicInvoke
.Invoke
总是可取的,除非你拥有的只是Delegate
和object[]
.对于性能比较,调试器外部的发布模式(控制台exe)中的以下内容将打印:
码: