日期:2014-05-17  浏览次数:21049 次

[C#] 谨慎使用DynamicInvoke

Delegate类提供了一个变参接口DynamicInvoke(params object[] args),可以在委托的具体类型不可知的情况下通过反射来进行委托调用。很方便,但由于变参,而且使用了反射,对性能有极大的影响。

设计实验:

定义一个委托(委托实例函数的内容为空,这个实验仅为检验调用开销,所以去掉了函数体,以避免额外干扰),对这个委托以不同的方式调用8×1024×1024次。

方案1——在明确委托类型的情况下直接调用委托

方案2——事先用一个Delegate变量承接委托实例,然后通过Delegate的DynamicInvoke方法调用委托

方案3——事先从委托中取出要调用的MethodInfo,然后通过MethodInfo的Invoke方法来调用委托

结果:方案1  约70ms,方案2  约8500ms ,方案3  约7500ms

很明显,在确定委托类型的情况下调用委托,就只有一次函数调用的开销,而通过Delegate类的DynamicInvoke反射调用委托就有了太多太多额外开销,事先获取委托的MethodInfo可以减少DynamicInvoke查找方法的那部分开销,但是同确定类型时的委托调用效率还是无法相比。另外方案3中在调用MethodInfo的Invoke方法前还做了一次参数到object[]数组的转化。因为Invoke方法只接受object[]参数,把这一步省掉的话,方案3的消耗可以降到6500ms左右,有好转,但不多。

所以,在能够确定委托类型的情况还是不要贪图方便使用Delegate的DynamicInvoke来代替正常的委托调用。