• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > C#中方法的直接调用、反射调用与Lambda表达式调用对比

C#中方法的直接调用、反射调用与Lambda表达式调用对比

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c#lambda表达式,c#中lambda表达式,c#lambda表达式 嵌套,c#lambda,c#中lambda等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

想调用一个方法很容易,直接代码调用就行,这人人都会。其次呢,还可以使用反射。不过通过反射调用的性能会远远低于直接调用——至少从绝对时间上来看的确是这样。虽然这是个众所周知的现象,我们还是来写个程序来验证一下。比如我们现在新建一个Console应用程序,编写一个最简单的Call方法。
class Program
{
    static void Main(string[] args)
    {
       
    }

    public void Call(object o1, object o2, object o3) { }
}
</div>
Call方法接受三个object参数却没有任何实现,这样我们就可以让测试专注于方法调用,而并非方法实现本身。于是我们开始编写测试代码,比较一下方法的直接调用与反射调用的性能差距:
static void Main(string[] args)
{
    int times = 1000000;
    Program program = new Program();
    object[] parameters = new object[] { new object(), new object(), new object() };
    program.Call(null, null, null); // force JIT-compile

    Stopwatch watch1 = new Stopwatch();
    watch1.Start();
    for (int i = 0; i < times; i++)
    {
        program.Call(parameters[0], parameters[1], parameters[2]);
    }
    watch1.Stop();
    Console.WriteLine(watch1.Elapsed + " (Directly invoke)");

    MethodInfo methodInfo = typeof(Program).GetMethod("Call");
    Stopwatch watch2 = new Stopwatch();
    watch2.Start();
    for (int i = 0; i < times; i++)
    {
        methodInfo.Invoke(program, parameters);
    }
    watch2.Stop();
    Console.WriteLine(watch2.Elapsed + " (Reflection invoke)");

    Console.WriteLine("Press any key to continue...");
    Console.ReadKey();
}
</div>
执行结果如下:
00:00:00.0119041 (Directly invoke)
00:00:04.5527141 (Reflection invoke)
Press any key to continue...
</div>

通过各调用一百万次所花时间来看,两者在性能上具有数量级的差距。因此,很多框架在必须利用到反射的场景中,都会设法使用一些较高级的替代方案来改善性能。例如,使用CodeDom生成代码并动态编译,或者使用Emit来直接编写IL。不过自从.NET 3.5发布了Expression相关的新特性,我们在以上的情况下又有了更方便并直观的解决方案。

了解Expression相关特性的朋友可能知道,System.Linq.Expressions.Expression<TDelegate>类型的对象在调用了它了Compile方法之后将得到一个TDelegate类型的委托对象,而调用一个委托对象与直接调用一个方法的性能开销相差无几。那么对于上面的情况,我们又该得到什么样的Delegate对象呢?为了使解决方案足够通用,我们必须将各种签名的方法统一至同样的委托类型中,如下:
public Func<object, object[], object> GetVoidDelegate()
{
    Expression<Action<object, object[]>> exp = (instance, parameters) =>
        ((Program)instance).Call(parameters[0], parameters[1], parameters[2]);

    Action<object, object[]> action = exp.Compile();
    return (instance, parameters) =>
    {
        action(instance, parameters);
        return null;
    };
}
</div>
如上,我们就得到了一个Func<object, object[], object>类型的委托,这意味它接受一个object类型与object[]类型的参数,以及返回一个object类型的结果——等等,朋友们有没有发现,这个签名与MethodInfo类型的Invoke方法完全一致?不过可喜可贺的是,我们现在调用这个委托的性能远高于通过反射来调用了。那么对于有返回值的方法呢?那构造一个委托对象就更方便了:
public int Call(object o1, object o2) { return 0; }

public Func<object, object[], object> GetDelegate()
{
    Expression<Func<object, object[], object>> exp = (instance, parameters) =>
        ((Program)instance).Call(parameters[0], parameters[1]);

    return exp.Compile();
}
</div>
至此,我想朋友们也已经能够轻松得出调用静态方法的委托构造方式了。可见,这个解决方案的关键在于构造一个合适的Expression<TDelegate>,那么我们现在就来编写一个DynamicExecuter类来作为一个较为完整的解决方案:

public class DynamicMethodExecutor
{
    private Func<object, object[], object> m_execute;

    public DynamicMethodExecutor(MethodInfo methodInfo)
    {
        this.m_execute = this.GetExecuteDelegate(methodInfo);
    }

    public object Execute(object instance, object[] parameters)
    {
        return this.m_execute(instance, parameters);
    }

    private Func<object, object[], object> GetExecuteDelegate(MethodInfo methodInfo)
    {
        // parameters to execute
        ParameterExpression instanceParameter =
            Expression.Parameter(typeof(object), "instance");
        ParameterExpression parametersParameter =
            Expression.Parameter(typeof(object[]), "parameters");

        // build parameter list
        List<Expression> parameterExpressions = new List<Expression>();
        ParameterInfo[] paramInfos = methodInfo.GetParameters();
        for (int i = 0; i < paramInfos.Length; i++)
        {
            // (Ti)parameters[i]
            BinaryE

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C#中方法的直接调用、反射调用与Lambda表达式调用对比
  • 理解C#中的Lambda表达式
  • 初步认识C#中的Lambda表达式和匿名方法
  • C#特性之匿名方法和Lambda表达式
  • C#中使用Lambda表达式自定义比较器实现两个列表合并实例
  • C#基础之Lambda表达式用法实例教程
  • C#3.0中Lambda表达式详解
  • C# 中如何利用lambda实现委托事件的挂接
  • C#用Lambda和委托实现模板方法

相关文章

  • 2017-05-28C#之WinForm WebBrowser实用技巧汇总
  • 2017-05-28C#难点逐个击破(4):main函数
  • 2017-05-28初步认识C#中的Lambda表达式和匿名方法
  • 2017-05-28探讨C#中Dispose方法与Close方法的区别详解
  • 2017-05-28c#目录操作示例(获取目录名称 获取子目录)
  • 2017-05-28C#中winform使用相对路径读取文件的方法
  • 2017-05-28讲解C#设计模式编程中享元模式的运用
  • 2017-05-28浅析C#数据类型转换的几种形式
  • 2017-05-28c#获取windows桌面背景代码示例
  • 2017-05-28C# webclient中文乱码问题解决方法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 在C#的类或结构中重写ToString方法的用法简介
    • C#、ASP.NET通用工具类IsWhat?(可以判断数字、身份证、数据类型等等)
    • C#定义的MP3播放类实例
    • C#中winform使用相对路径读取文件的方法
    • C#读取目录下所有指定类型文件的方法
    • C#实现读取DataSet数据并显示在ListView控件中的方法
    • C#实现启动,关闭与查找进程的方法
    • C#无法打开计算机“.”上的 IISADMIN 服务的解决方法
    • 解读在C#中winform程序响应键盘事件的详解
    • C# Base 64 编码/解码实现代码

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有