https://www.cnblogs.com/nicholashjh/p/7928205.html

首先定义一个泛型委托类型,如下:

public delegate T Function<T>(T a, T b);

实现泛型委托的主体代码,并调用:

 1 public static string Add(string a, string b)
2   {
3     return string.Format("{0} #### {1}",a,b);
4   }
5 //实名委托方式
6 Function<string> func = new Function<string>(Add);
7 Console.WriteLine( func("hello", "world") );
8
9 //匿名委托方式
10 Function<string> func1 = new Function<string>(delegate(string a, string b) {
11 return string.Format("{0} @@@@ {1}",a,b);
12 });
13 Console.WriteLine(func1("hello", "world"));
14
15 //Lambda表达式方式
16 Function<string> func2 = (a, b) => string.Format("{0} **** {1}", a, b);
17 Console.WriteLine(func2("hello", "world"));
18
19 Expression<Function<string>> func2_0;
20 //func2_0 = func; //不支持将委托直接赋值给表达式树
21 //func2_0 = func1; //不支持将委托直接赋值给表达式树
22 //func2_0 = func2; //不支持将委托直接赋值给表达式树
23
24 //(a, b) => string.Format("{0} **** {1}", a, b)语句块的类型是lambda expression,即我们常说的lambda表达式
25 //所以,func2_0 = (a, b) => string.Format("{0} **** {1}", a, b)的直接赋值是没有问题的。
26 func2_0 = (a, b) => string.Format("{0} **** {1}", a, b);
27 Console.WriteLine(func2_0.Compile()("hello", "world"));

以上代码展示了委托类型Function<T>主体定义的四种方式,分别是实名委托、匿名委托、Lambda表达式、expression表达式树。

从Function<T>委托主体的代码定义来看是越来越简单和友好,这些变化很大部分应归功于C#的语法糖。

总结:不管委托主体在编写的形式上怎么简化,但依然改变不了它委托类型的本质,当委托代码块被调用时会即时执行。

随着C#的发展,后来加入了expression这个东东,简称表达式树,我想用过ling to sql、linq to entity、linq to xml等等的你是不会陌生的。
expression是一种数据结构,我们可以将平常编写的C#语句块(或者叫表达式)的各部分进行分解并存入这个树结构当中,保存在expression树结构中的语句块是不能直接执行的。
当我们需要将expression结构中的数据抽取并还原时就需要调用expression.Compile()方法,这里我称之为编译。编译后得到的结果就是我们之前存入的语句块,这是数据结构还原成语句块的过程(这是一个比喻)。
当然将数据还原成语句块时依据解析引擎的不同会产生不同的输出结果,如果引擎是linq to sql那么解析后输出的就是可供数据库执行的sql,如果引擎是linq to xml则解析后输出的是Xpath之类的表达式(没亲自验证)

下面就请你和我一起来体验一下expression表达式数据的存储和编译输出吧!!!!仍以上面的场景为例子

 1 //expression表达式树主体构造开始
2 ParameterExpression paramA = Expression.Parameter(typeof(object), "a"); //声明Lambda表达式中的参数表达式a
3 ParameterExpression paramB = Expression.Parameter(typeof(object), "b"); //声明Lambda表达式中的参数表达式b
4 ConstantExpression constantExp = Expression.Constant("{0} !!!!! {1}",typeof(string));//声明文本块常量表达式
5 MethodCallExpression bodyExp = Expression.Call(typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(object), typeof(object) })
6 , new Expression[] { constantExp, paramA, paramB }); //声明String.Format()方法调用表达式
7 //expression表达式树主体构造结束
8
9
10 //1.构造类型为LambdaExpression的lambda表达式树,编译后得到委托的基元类型(弱类型)。
11 LambdaExpression func3 = Expression.Lambda(bodyExp, paramA, paramB);//将以上各个表达式部分组合为Lambda表达式
12 Delegate dg = func3.Compile();//编译表达式树得到委托
13 Console.WriteLine(dg.DynamicInvoke("hello", "world"));//调用委托并将结果输出到控制台
14 //Console.WriteLine(func3.Compile().DynamicInvoke("hello", "world")); //上面两步可以简化为这句代码
15
16 //2.构造类型为Expression<Function<string>>的泛型lambda表达式树,编译后得到委托可直接调用。
17 Expression<Function<string>> func4 = Expression.Lambda<Function<string>>(bodyExp, paramA, paramB);
18 Console.WriteLine(func4.Compile()("xxxx", "yyyy"));
19
20 //3.构造类型为Expression<Func<string, string, string>>的泛型lambda表达式树,编译后得到委托可直接调用。
21 //与上面的区别是这里用系统定义的Func<in T1, in T2, out TResult>泛型委托代替了自定义的Function<T>委托。
22 Expression<Func<string, string, string>> func5 = Expression.Lambda<Func<string, string, string>>(bodyExp, paramA, paramB);
23 Console.WriteLine(func5.Compile()("yyyy", "zzzz"));
24
25 //以上总结了expression表达式的创建和调用的不同方式,以下是几个有关expression的扩展例子
26 //4.动态构造string.Concat("hello", "world")语句块
27 var concatMethod = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string) });
28 var addExpr = Expression.Add(Expression.Constant("hello "), Expression.Constant("world"), concatMethod);
29 Expression<Func<string>> e = Expression.Lambda<Func<string>>(addExpr);
30 Console.WriteLine(e.Compile()());
31
32 //5.动态构造Math.Sin(100)语句块
33 ParameterExpression expA = Expression.Parameter(typeof(double), "a"); //参数a
34 MethodCallExpression expCall = Expression.Call(
35 typeof(Math).GetMethod("Sin",new Type[]{typeof(double)}),expA);
36 LambdaExpression exp = Expression.Lambda(expCall, expA); // a => Math.Sin(a)
37 Console.WriteLine( exp.Compile().DynamicInvoke(100) );
38
39 //6.动态构造Console.WriteLine("aaa")语句块
40 ConstantExpression _constExp = Expression.Constant("aaa", typeof(string));//一个常量
41 MethodCallExpression _methodCallexp = Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), _constExp);
42 Expression<Action> consoleLambdaExp = Expression.Lambda<Action>(_methodCallexp);
43 consoleLambdaExp.Compile()();

.net 系列:Expression表达式树、lambda、匿名委托 的使用【转】的更多相关文章

  1. .net 系列:Expression表达式树、lambda、匿名委托 的使用

    首先定义一个泛型委托类型,如下: public delegate T Function<T>(T a, T b); 实现泛型委托的主体代码,并调用: public static strin ...

  2. 委托、匿名委托、Lambda 表达式、Expression表达式树之刨根问底

    本篇不是对标题所述之概念的入门文章,重点在阐述它们的异同点和应用场景.各位看官,这里就不啰嗦了,直接上代码. 首先定义一个泛型委托类型,如下: public delegate T Function&l ...

  3. .NET技术-6.0. Expression 表达式树 生成 Lambda

    .NET技术-6.0. Expression 表达式树 生成 Lambda public static event Func<Student, bool> myevent; public ...

  4. C# 表达式树Lambda扩展(四)

    一.前言 本来计算这篇文章在后面需要运用的时候写的,但是既然写到表达式的扩展呢,就一起写完吧. 看到这个标题就有一种疑问,Lambda表达式本来就是表达式树,还需要怎么扩展?那就看看下面的内容,你就知 ...

  5. LINQ to Objects系列(4)表达式树

    为了进一步加深对Lambda表达式的理解,我们需要掌握一个新的知识,Lambda表达式树,可能听名字看起来很高深和难以理解,但实际上理解起来并没有想象中那么难,这篇文章我想分以下几点进行总结. 1,表 ...

  6. Expression表达式树(C#)

    Lambda表达式: 1.下面举例通过Lambda表达式创建了一个用于验证Name的Func委托. //通过Lambda表达式创建一个对象的Name属性验证委托 Func<SearchInfo, ...

  7. 介绍一个可以将Expression表达式树解析成Transact-SQL的项目Expression2Sql

    一.Expression2Sql介绍 Expression2Sql是一个可以将Expression表达式树解析成Transact-SQL的项目.简单易用,几分钟即可上手使用,因为博主在设计Expres ...

  8. Expression表达式树

    表达式树表示树状数据结构的代码,树状结构中的每个节点都是一个表达式,例如一个方法调用或类似 x < y 的二元运算 1.利用 Lambda 表达式创建表达式树 Expression<Fun ...

  9. 关于Expression表达式树的拼接

    最近在做项目中遇到一个问题,需求是这样的: 我要对已经存在的用户进行检索,可以根据用户的id 或者用户名其中的一部分字符来检索出来,这样就出现了三种情况 只有id,只有用户名中一部字符,或者全部都有. ...

随机推荐

  1. 小成就之解决调用spring中FileSystemXmlApplicationContext路径问题

    此文写下调用spring过程中遇到的一个问题!或许对于入行的人一看觉得我很傻逼吧,这问题谁都会了!但我觉得对于新手(自已)来说,算是一个好思路与好办法! 问题: 对于 test_aa ta = (te ...

  2. win7 64位系统pdf预览

    装了Win7 64位以后,发现pdf文件不能正常预览,相信很多朋友也遇到了同样的问题,之前搜索的结果有个办法是安装Foxit的插件(相信有不少原来用Adobe Reader的用户从此改用Foxit了) ...

  3. 谷歌浏览器测试工具应用Advanced REST client

    1.2 http post 在URL栏输入http://httpbin.org/post,选在”POST”类型,在”Payload”栏输入data,最后设置”Content-Type”

  4. BZOJ.2716.[Violet3]天使玩偶(CDQ分治 坐标变换)

    题目链接 考虑对于两个点a,b,距离为|x[a]-x[b]|+|y[a]-y[b]|,如果a在b的右上,那我们可以把绝对值去掉,即x[a]+y[a]-(x[b]+y[b]). 即我们要求满足x[b]& ...

  5. BZOJ4205 : 卡牌配对

    对于两张卡牌,如果存在两种属性值不互质,则可以匹配. 只考虑200以内的质数,一共有46个,可以新建3*46*46个点来表示一类属性值中有这两种质数的卡牌. 然后对于每张卡牌,枚举它的质因子,最多只有 ...

  6. ThreadLocal 详解

    什么是ThreadLocal 根据JDK文档中的解释:ThreadLocal的作用是提供线程内的局部变量,这种变量在多线程环境下访问时能够保证各个线程里变量的独立性. 从这里可以看出,引入Thread ...

  7. Delphi 资源管理器套件

    需要个类似资源管理器的东西, 首先试了下 TDriveComboBox.TDirectoryListBox.TFileListBox, 嘿! Win31 时代的东西, 不是一般地丑. 试了下 Vcl. ...

  8. 10 个理由让你继续干 IT

    1.钱,钱,钱 对,我们努力工作就是为了赚钱,而IT专业人士的努力工作的确得到了很好的补偿.报酬不仅仅是好而已,而是非常棒.根据美国劳工部<2010年美国 就业与报酬情况概览>(表6,PD ...

  9. 分享下使用 svn,测试服务器代码自动更新、线上服务器代码手动更新的配置经验

    分享下使用 svn,测试服务器代码自动更新.线上服务器代码手动更新的配置经验 利用SVN的POST-COMMIT钩子自动部署代码 Linux SVN 命令详解 Linux SVN 命令详解2 使用sv ...

  10. ShellExecuteA URLDownloadToFileA

    ExeFile(Handle,nil,PChar('cmd.exe'),PChar('/c C:\123.exe'),nil,SW_SHOWNORMAL); c_md5 := 'cmd.exe /c ...