博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lambda表达式和表达式树
阅读量:6067 次
发布时间:2019-06-20

本文共 2775 字,大约阅读时间需要 9 分钟。

一: Lambda表达式

首先,表达式的类型本身并非委托类型,但它可以通过多种方式隐式或者显式地转换成一个委托实例。匿名函数这个术语同时涵盖了匿名方法和Lambda,很多情况下两者可以使用相互转换原则。

1.用匿名方法创建委托实例。                     
Func
returnlength = delegate(string text) { return text.Length; };
对照的直接用lambda形式实现上述方法,代码如下:
Func
returnlength = (string text) => { return text.Length; };
等同于
Func
returnlength = (string text) => text.Length;
或者
Func
returnlength = (text) => text.Length;
在阅读lanbda表达式时,可以将 => 部分看成 ”goes to“。

 一: 表达式树

1.1基本知识

表达式树提供了一种抽象的方式将一些代码表示成一个对象树,表达式树主要用于LINQ,树中的每个节点本身都是一个表达式。

不同的表达式类型代表能在代码中执行的不同操作:二元操作,一元操作,方法调用,构造函数调用等等。

System.Linq.Expressions命名空间包含了代表表达式的各个类,它们都继承自Expression,一个抽象的主要包含一些静态工厂方法的类,这些方法用于创建其他表达式类的实例,然而,Expression类也包括两个属性。

1.Type属性代表表达式求值后的.NET类型,可把它视为一个返回类型。例如一个表达式要获取一个字符串的Length属性,该表达式的类型就是int。

2.NodeType属性返回所代表的表达式的种类。它是ExpressionType枚举的成员,包括LessThan、Multiply和Invoke等。仍然使用上面的例子,对于myString.Length这个属性访问来说,其节点类型是MemberAccess。。

并且该属性能区分由相同的类表示的不同种类的表达式。

示例如下:

Expression first = Expression.Constant(2);    Expression second = Expression.Constant(3);    Expression add = Expression.Add(first, second);

      Func<int> acmpiled = Expression.Lambda<Func<int>>(add).Compile();   //编译成可执行的委托方法。

Debug.Write(add);

该代码会产生输出“(2+3)”,这意味着这些表达式树类覆盖了ToString来产生可读的输出。

注意:“叶”表达式在代码中是最先创建的,我们需要自上而下构建这些表达式。

1.2表达式树与委托

LambdaExpression是从Expression派生的类型之一,泛型类 Expression<TDelegate>又是从LambdaExpression派生的。Expression与 Expression<TDelegate>的区别在于:泛型类以静态类型的方法标识了它是什么种类的表达式,也就是说,他确定了返回类型和参数。所以显然,TDelegate必须是一个委托类型。

注意:并非所有的Lambda表达式都能转换成表达式树。不能将带有一个语句块(即使只有一个return语句)的Lambda转换成表达式树,只有对单个表达式进行求值的lambda才可以。表达式中不能包含赋值操作,因为在表达式中表示不了这种操作。

示例二如下:

Expression
> expression = (x, y) => x.StartsWith(y); Func
complied = expression.Compile(); Debug.Write(complied("first", "second")); Debug.Write(complied("first", "fir"));

示例二等同于如下代码:

//构造调用方法的各个组件            MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) }); //方法            ParameterExpression target= Expression.Parameter(typeof(string), "x"); //方法主            var methodArg = Expression.Parameter(typeof(string), "y"); //参数            Expression[] methodArgs = new [] { methodArg };  //参数列表            MethodCallExpression call = Expression.Call(target, method, methodArgs); //从以上组件创建CallExpression            //将call转换为lambda表达式            ParameterExpression[] lambdaParameters = new[] { target, methodArg };  //参数            var lambda = Expression.Lambda
>(call, lambdaParameters); Func
complied = lambda.Compile(); Debug.Write(complied("first", "second")); Debug.Write(complied("first", "fir"));

 

转载于:https://www.cnblogs.com/caoheyang911016/p/4272574.html

你可能感兴趣的文章
linux基础-第十四单元 Linux网络原理及基础设置
查看>>
浅谈一下Windows下的用户权限
查看>>
什么是linux的ftp
查看>>
Python命令行解析argparse常用语法使用简介
查看>>
Spring 4 官方文档学习(十二)View技术
查看>>
jsp页面验证码(完整实例)
查看>>
学习建模 - UML
查看>>
Android解析WindowManager(一)WindowManager体系
查看>>
一个想法(续二):换个角度思考如何解决IT企业招聘难的问题!
查看>>
tomcat指定配置文件路径方法
查看>>
一些常见的关于Linux系统的问题
查看>>
推荐一款jQuery ColorPicked 颜色拾取器插件
查看>>
javaweb学习总结(二十三)——jsp自定义标签开发入门
查看>>
网络编程中的CAP & 有趣的存储框架(关系型、NoSQL)全图
查看>>
[Linux内核]ctrl-z/fg/bg/nohup/setsid/()与&/disown/screen
查看>>
VS没办法调试,直接退出,报错:1. 使用调试生成配置或禁用调试选项“启用‘仅我的代码’”。。。...
查看>>
C# 委托应用总结
查看>>
Linux驱动技术(七) _内核定时器与延迟工作
查看>>
裁判文书网采集说明
查看>>
Reverse Engineering Custom DataTypes -> GUID() in SQL Server to PostgreSQL
查看>>