性能测试

先放结果,经过多次性能测试并取得平均值:

明确类型的委托:执行时间: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来执行方法,通过测试可以看出,反射与不明确类型的委托执行原理基本相同,很明显的空间换时间。