16.C#初见Lambda表达式及表达式树(九章9.1-9.3)
在说明Lambda相关知识前,我们需要了解Lambda表达式常用于LINQ,那么我们来聊下LINQ。
LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态。这些操作表示了各种关于数据的逻辑:如何过滤、如何排序以及如何将不同的数据源连接在一起,等等。执行委托只是LINQ的众多能力之一。为了富有效率地使用数据库和其他查询引擎,我们需要以一种不同的方式来表示管道中的各个操作。这种不同的方式就可以使用Lambda表达式来表现。下面分别使用委托(使用匿名函数)和Lambda表达式来作出同样的事情:返回一个人的到现在一共活了多少天。
class Person
{
public DateTime BirthDay { get; set; }
} public delegate int GetLifeDays(Person p);//声明一个委托类型
static void Main(string[] args)
{
Person p = new Person() { BirthDay = new DateTime(, , ) }; GetLifeDays gfd = delegate (Person x) { //实例化一个委托
return (DateTime.Now - x.BirthDay).Days;
};
Console.WriteLine(gfd(p)); GetLifeDays gfd1 = (Person x) => { return (DateTime.Now - x.BirthDay).Days; };
Console.WriteLine(gfd1(p)); GetLifeDays gfd2 = (Person x) => (DateTime.Now - x.BirthDay).Days; //去除了后面的大括号,“;”为表达式结束,不是Lambda的结束
Console.WriteLine(gfd2(p)); GetLifeDays gfd3 = (x) => { return (DateTime.Now - x.BirthDay).Days; }; //让编译器推断参数的类型
Console.WriteLine(gfd3(p)); GetLifeDays gfd4 = (x) => (DateTime.Now - x.BirthDay).Days; //同时省去参数类型和大括号
Console.WriteLine(gfd4(p)); GetLifeDays gfd5 = x => (DateTime.Now - x.BirthDay).Days; //再进一步,省去参数列表的括号
Console.WriteLine(gfd5(p)); Console.ReadKey();
}
上述是单一参数的各种情况,对于有两个或多个参数的,效果是"一个到到从出生到某一天的相隔天数",某一天肯定是要大于出生那天啦。
public delegate int GetDaysTo(Person p, DateTime d);
static void Main(string[] args)
{
Person p = new Person() { BirthDay = new DateTime(, , ) }; DateTime d = new DateTime(, , );
//使用匿名方法
GetDaysTo gdt = delegate (Person x, DateTime y)
{
return (y - x.BirthDay).Days;
};
Console.WriteLine(gdt(p, d)); GetDaysTo gdt1 = (Person x, DateTime y) => { return (y - x.BirthDay).Days; };
Console.WriteLine(gdt1(p, d)); GetDaysTo gdt2 = (Person x, DateTime y) => (y - x.BirthDay).Days;
Console.WriteLine(gdt2(p, d)); GetDaysTo gdt3 = (x, y) => (y - x.BirthDay).Days;
Console.WriteLine(gdt3(p, d)); //GetDaysTo gdt4 = x, y => (y - x.BirthDay).Days; Error
//Console.WriteLine(gdt4(p, d)); Console.ReadKey();
}
可以看出当参数为两个或两个以上时,不能省略参数列表中的括号,那也可以想像在语句两条或两条以上时,不能省略大括号。
下面结合之前的知识,对一个列表使用ambda表达式进行操作。
//使用集合初始化器
List<Person> l = new List<Person> {
new Person { BirthDay=new DateTime(,,)},
new Person { BirthDay=new DateTime(,,)},
new Person { BirthDay=new DateTime(,,)},
new Person { BirthDay=new DateTime(,,)},
new Person() { BirthDay=new DateTime(,,)}
}; //找到大于new DateTime(1890,1,1)的人
var result0 = l.FindAll(x => x.BirthDay > new DateTime(, , )); //按年龄从小到大排序
l.Sort((x, y) => x.BirthDay > y.BirthDay ? - : );
foreach (var e in l)
{
Console.WriteLine((DateTime.Now - e.BirthDay).Days);
} //循环打印每个人的出生天数,效果和上面的foreach一样
l.ForEach(x => Console.WriteLine((DateTime.Now - x.BirthDay).Days)); //找到BirthDay=new DateTime(1890,12,12)的人
var result1 = l.Find(x => x.BirthDay == new DateTime(, , ));
接下来,我们来说下表达式树,.NET3.5的表达式提供了一种抽象的方式将一些代码表示成一个对象树,表达式树主要用于LINQ。System.Linq.Expressions命名空间包含了代表表达式的各个类,它们都继承于Expression,一个抽象的主要包含一些静态工厂方法的类,这些方法用于创建其它表达类的实例。
Expression类包含两个属性:
- Type属性代表表达式求值后.NET类型,可把它视为一个返回类型。例如,一个表达式要获取一个字符串的长度,则该表达式的类型为int。
- NodeType属性返回所代表的表达式的种类。它是ExpressionType枚举的成员。
Expression first = Expression.Constant();
Expression result = Expression.Add(first, first);
Console.WriteLine(result);
断点对象各属性


上图分别为first对象和result对象的各属性值。
- 将表达式树编译成委托
LambdaExpression是从Expression派生的类型之一。泛型类Expression<TDelegate>又是从LambdaExpression中派生。Expression和Expression<TDelegate>区别在于泛型类以静态类的方法标识了它是什么各类的表达式,也就是说,它确定了返回类型和参数。很显然,这是用TDelegate类型参数来表示的,它必须是一个委托类型。LambdaExpression有一个Compile方法能创建恰当类型的委托。Expression<TDelegate>也有一个同名的方法 ,但它静态类型化返回TDelegate类型的委托。如:
Expression first = Expression.Constant();
Expression result = Expression.Add(first, first);
Func<int> add = Expression.Lambda<Func<int>>(result).Compile();
Console.WriteLine(add()); //
- 将C#Lambda表达式转换为表达式树
Lambda表达式能显式或隐式地转换为恰当的委托实例,然而这些并非唯一能进行的转换,还可以要求编译器通过你的Lambda表达式构建一个表达式树,在执行时创建Expression<TDelegate>的一个实例。如
Expression<Func<int>> re = () => ;
Func<int> add0 = re.Compile();
Console.WriteLine(add0());
后面的那些内容真心太复杂了,自己实在理解不了,而且日常使用中也没有使用过,没有底气聊这个话题,想深入的朋友可以自己深入去了解,这里就做罢了吧。
请斧正。
16.C#初见Lambda表达式及表达式树(九章9.1-9.3)的更多相关文章
- C#中的Lambda表达式和表达式树
在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...
- Lambda表达式和表达式树
在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...
- C#复习笔记(4)--C#3:革新写代码的方式(Lambda表达式和表达式树)
Lambda表达式和表达式树 先放一张委托转换的进化图 看一看到lambda简化了委托的使用. lambda可以隐式的转换成委托或者表达式树.转换成委托的话如下面的代码: Func<string ...
- 深入学习C#匿名函数、委托、Lambda表达式、表达式树类型——Expression tree types
匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...
- lambda表达式和表达式树(深入理解c#)
1.Lambda形式 1). Lambda表达式最冗长的形式: (显式类型的参数列表)=>{语句} 2). 大多数时候,都可以用一个表达式来表示主体,该表达式的值是Lambda的结果,在这些情况 ...
- C# 表达式树 创建、生成、使用、lambda转成表达式树~表达式树的知识详解
笔者最近学了表达式树这一部分内容,为了加深理解,写文章巩固知识,如有错误,请评论指出~ 表达式树的概念 表达式树的创建有 Lambda法 和 组装法. 学习表达式树需要 委托.Lambda.Func& ...
- 无法将具有语句体的lambda表达式转换为表达式树
很早就碰到了这个问题,当时也没有深入的研究,趁着空闲,遂把这个问题研究清楚. (一)普通案例 下面从一个普通的案例入手,下面准备两个List集合,都是放在内存里面的(需要模拟到远端执行的时候,我们是通 ...
- [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门
[.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习 ...
- [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用
[.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用 本节导读:讨论了表达式树的定义和解析之后,我们知道了表达式树就是并非可执行代码,而是将表达式对象化后的数据结构.是 ...
随机推荐
- ASP.NET中iframe框架点击左边页面链接,右边显示链接页面内容
首先是主页面main.aspx <body style="background-color: #AFEEEE"> <form id="form1&quo ...
- 03_汇编语言(n个数找最大值)
程序要求: 先输入一个数n(0<n<=100),再输入n个无符号数K(0<=K<=65535),找出这n个数的最大值并输出 测试实例保证输入每个数之后,都会以回车结束 代码: ...
- (一)openwrt源码目录概述
前言 这段时间总是在和openwrt打交道,之前也零零散散地写过一点,还是希望能有点体系.还记得我刚看到源代码的时候,觉得无从下手.我想从Makefile的整个执行过程入手,搞清楚编译源代码的几个小时 ...
- VS2010 调试窗口一闪而过解决方法
若此时进行的操作是编译(F5),可先运行程序(Ctrl+F5),若仍然一闪而过,用下面方法解决. 方法一: 1.要有头文件cstdlib,在程序最后写一句(return之前)添加:system(&qu ...
- 限制input输入类型(多种方法实现)
1.只能输入和粘贴汉字 <input onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste= ...
- phpcms v9 下拉菜单 二级 三级子栏目调用方法
很多网站的导航栏可以实现下拉二级菜单,三级菜单等效果,今天我们就来分享phpcms v9 支持下拉菜单的方法,可以支持无限子栏目调用,具体写法如下: <ul> {pc:content ac ...
- redis 一二事 - 设置过期时间,以文件夹形式展示key显示缓存数据
在使用redis时,有时回存在大量数据的时候,而且分类相同,ID相同 可以使用hset来设置,这样有一个大类和一个小分类和一个value组成 但是hset不能设置过期时间 过期时间只能在set上设置 ...
- Windows远程连接MAC桌面
一.准备软件 VNC Server (MAC OS X已支持) RealVNC/TightVNC 二.MAC OS X设置 注:Mac OS X 10.5 已经支持了VNC Viewer访问的功能,设 ...
- ZGrapher 画函数曲线图的工具
可以下载个绿色版,我下载的是 ZGrapher 1.4 绿色版.下面先看下图出来的图: 然后可以在“file"->"Save as Picture ..." -&g ...
- sqlzoo.net刷题2
Find the largest country (by area) in each continent, show the continent, thename and the area: 找到每个 ...