当您有一个委托实例时,您可能知道确切的类型,或者您可能只知道它是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
个参数基本上,尽可能避免DynamicInvoke
次.Invoke
总是比较好的,除非你只有Delegate
和object[]
.
为了进行性能比较,将在调试器(控制台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);