经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
C# 表达式树的知识详解
来源:cnblogs  作者:痴者工良  时间:2018/11/30 9:43:05  对本文有异议

笔者最近学了表达式树这一部分内容,为了加深理解,写文章巩固知识,如有错误,请评论指出~


表达式树的概念

  • 表达式树的创建有 Lambda法组装法

  • 学习表达式树需要 委托、Lambda、Func<> 基础。

  • 表达式树 形状可以参考 二叉树。

  • 可以把表达式树理解成 数学表达式。

    数学表达式的所有常量、符号为表达式树的底节点。每一次计算生成的结果是一个结点,或者说他们的共同结点就是他们应该进行的运算。


生成表达式树

表达式树的创建有 Lambda表达式法组装法

为了方便,这里指定生成的表达式为 ( i * j ) + ( x * y )

他们的运算是这样的

Lambda 生成表达式树

 在控制台创建应用,需要引入 

  1. using System.Linq.Expressions;

  1,创建表达式

    (系统自动把 Lambda表达式 转为表达式树,当然,不是所有的 Lambda表达式都能转为表达式树,详细请参考文章后面的“系统自动把 Lambda表达式 转为 表达式树” 一节)

  1.  Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (* j) + (* y);

  2,输出系统转换的表达式

    输入这一行代码后运行,看看控制台输出的表达式树

  1. Console.WriteLine(func);

  3,把代码转为数据

    (把代码当作数据来使用)

  1. var compile = func.Compile();      
  2.             //或 Func<int, int, int, int, int> compile = func.Compile();

  4,代入运算

  1.             int result = compile(12, 13, 14, 15);       //把具体数字代入表达式并运算
  2.             Console.WriteLine(result);      //输出表达式结果

完整代码如下

  1.            Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (* j) + (* y);
  2.             Console.WriteLine(func);        //输出表达式var compile = func.Compile();       //把代码转为数据//或 Func<int, int, int, int, int> compile = func.Compile();int result = compile(12, 13, 14, 15);       //把具体数字代入表达式并运算Console.WriteLine(result);      //输出表达式结果Console.ReadKey();

控制台输出

 

组装法生成表达式树

表达式由 "符号" 和 运算符组成,。

使用 ParameterExpression 类型 来修饰参数,使用 Expression.Parameter(Type type,string name) 实例化参数。

  1,生成 a b  d 参数 

  1.         ParameterExpression a = Expression.Parameter(typeof(int), "i");
  2.             ParameterExpression b = Expression.Parameter(typeof(int), "j");
  3.             ParameterExpression c = Expression.Parameter(typeof(int), "x");
  4.             ParameterExpression d = Expression.Parameter(typeof(int), "y");

 

  分析:

     i、j、x、y 是结点名称,a、b、c、d 是实例名称。不用留精力思考我上面 a b c d i j x y 的名称设定。

    ParameterExpression 表示创建一个节点,Parameter 表示一个命名的参数表达式,详细请参考文章后面的 “Expression 参数分类”

    Expression.Parameter(Type type,string name) 表示这个节点的属性。

  2,生成结点

  1.             Expression r1 = Expression.Multiply(a, b);      //乘法运行Expression r2 = Expression.Multiply(c, d);      //乘法运行

 

  分析:

    创建了 ( i * j )( x * y ) 两个运算

    Multiply 表示 不进行溢出检查的乘法运算。Expression 里有 85种 操作方法,更多加减乘除比较大小等操作在文章后面详细附上,参考 “ 运算操作符” 一节。

  3,生成终结点

  1. Expression result = Expression.Add(r1, r2);     //相加

  4,生成表达式树、转换、输出表达式树、代入数据进行运算

  1.             Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);var com = func.Compile();
  2.             Console.WriteLine("表达式" + func);
  3.             Console.WriteLine(com(12, 12, 13, 13));

 

完整代码如下

  1.             ParameterExpression a = Expression.Parameter(typeof(int), "i");
  2.             ParameterExpression b = Expression.Parameter(typeof(int), "j");
  3.  
  4.             Expression r1 = Expression.Multiply(a, b);      //乘法运行ParameterExpression c = Expression.Parameter(typeof(int), "x");
  5.             ParameterExpression d = Expression.Parameter(typeof(int), "y");
  6.             Expression r2 = Expression.Multiply(c, d);      //乘法运行Expression result = Expression.Add(r1, r2);     //相加//以上代码产生结点//生成表达式Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);var com = func.Compile();
  7.             Console.WriteLine("表达式" + func);
  8.             Console.WriteLine(com(12, 12, 13, 13));
  9.             Console.ReadKey();

控制台界面


 

补充说明

  1,系统自动把 Lambda表达式 转为 表达式树

    对 lambda表达式 的要求 只能 由 传入参数 和 返回参数 两部分表示。lambda表达式 不能包含其它判断、循环等的代码。

      错误举例

  1.             Expression<Func<int, int, int, int, int>> func = (a, b, c, d) =>{if (< 10)
  2.                 {
  3.                     a += 1;
  4.                 }/* * 其它操作代码                 */return a + b + c + d;
  5.             };

View Code

 

      把那些东西通通删除,修改后:

  1.  Expression<Func<int, int, int, int, int>> func = (a, b, c, d) => a + b + c + d;

  这样的 “最简” 的 lambda表达式 才能被系统自动转为表达式树

  2,运算操作符

     一般数学上,有加减乘除、取余、求幂等操作,而在程序中,运算操作符可以有更多的选择,达 85 种。

      笔者这里给出一张图列出部分方法。

微软官方 的操作运算符列表 https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.expressions.expression?view=netframework-4.7.2

估计大家看微软的文档会有点不爽~这里推荐大神翻译、整理的列表 https://blog.csdn.net/zhuqinfeng/article/details/70168337

3,Expression 参数

以数学 椭圆周长公式:L = 2πb + 4(a-b)  ,a 为长半轴,b 为短半轴, 进行举例 

Parameter 类似于 数学的 未知数 如 a 、 b;使用方法 

  1. ParameterExpression a = Expression.Parameter(typeof(int), "a")
  1. ParameterExpression b = Expression.Parameter(typeof(int), "b")

Constant 表示一个常数,例如 2πb 中的 2 或者 2π ;使用方法

  1. ConstantExpression define = Expression.Constant(2);

  其它更多参数分类 请查看 https://blog.csdn.net/zhuqinfeng/article/details/70168337

这里附上部分截取图片

4,Expression 的操作方法

表示加减乘除等运算的方法。以下图举例

Multiply(a,b) 为乘法,Add(r1,r2) 为加法。

当然,并没有这么简单,他们都有相关的重载方法和高级的使用用途。

请查看 https://blog.csdn.net/zhuqinfeng/article/details/70168337

这里给出部分截图

 5,表达式树的高级用法

表达式树可以结合 数据库查询 或 Linq,衍生很多高级操作。

例如 动态查询、遍历表达式树、转成成 SQL where 子句等等,限于幅度,笔者不再赘述。

下面的链接可以查看 System.Linq.Expressions 的所有类型对象。https://docs.microsoft.com/zh-cn/dotnet/api/System.Linq.Expressions?view=netframework-4.7.2

好好学习,天天向上~期望 3号面试成功

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号