性能测试
先放结果,经过多次性能测试并取得平均值:
明确类型的委托:执行时间:41, 内存消耗:64120
不明确类型的委托:执行时间:6339,内存消耗:1524224
通过反射Invoke执行:执行时间:1087,内存消耗:4344552
明确类型的委托
委托作为C#特殊类型,在明确委托类型下编译器则会特殊照顾,在委托类中生成隐藏的函数,如System.Action<T>的Invoke函数:
.method public hidebysig newslot virtual instance void Invoke ( !T obj ) runtime managed { .custom instance void __DynamicallyInvokableAttribute::.ctor() = ( 01 00 00 00 ) }
因为知道确切的参数类型,占用的大小,以及函数的位置,可以直接进行调用,在IL层面使用callvirt指令,因此明确类型的委托是速度最快的。
不明类型的委托
不明类型的委托,或者将委托退化成System.Delegate类型,通过Delegate.DynamicInvoke进行动态调用,需要进行多部:
获取运行时(Runtime)的方法信息,如委托封装的Target目标类型等信息。
获取形参信息(ParameterInfo)等元数据,对传入的参数列表进行类型检查。
通过调用RuntimeMethodHandle.InvokeMethod传给CLR,由CLR内部处理调用。
该过程过于复杂,增加了很长的调用时间。
反射
通过MethodInfo.Invoke来执行方法,通过测试可以看出,反射与不明确类型的委托执行原理基本相同,很明显的空间换时间。