在说明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类包含两个属性:

  1. Type属性代表表达式求值后.NET类型,可把它视为一个返回类型。例如,一个表达式要获取一个字符串的长度,则该表达式的类型为int。
  2. 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)的更多相关文章

  1. C#中的Lambda表达式和表达式树

    在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...

  2. Lambda表达式和表达式树

    在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...

  3. C#复习笔记(4)--C#3:革新写代码的方式(Lambda表达式和表达式树)

    Lambda表达式和表达式树 先放一张委托转换的进化图 看一看到lambda简化了委托的使用. lambda可以隐式的转换成委托或者表达式树.转换成委托的话如下面的代码: Func<string ...

  4. 深入学习C#匿名函数、委托、Lambda表达式、表达式树类型——Expression tree types

    匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...

  5. lambda表达式和表达式树(深入理解c#)

    1.Lambda形式 1). Lambda表达式最冗长的形式: (显式类型的参数列表)=>{语句} 2). 大多数时候,都可以用一个表达式来表示主体,该表达式的值是Lambda的结果,在这些情况 ...

  6. C# 表达式树 创建、生成、使用、lambda转成表达式树~表达式树的知识详解

    笔者最近学了表达式树这一部分内容,为了加深理解,写文章巩固知识,如有错误,请评论指出~ 表达式树的概念 表达式树的创建有 Lambda法 和 组装法. 学习表达式树需要 委托.Lambda.Func& ...

  7. 无法将具有语句体的lambda表达式转换为表达式树

    很早就碰到了这个问题,当时也没有深入的研究,趁着空闲,遂把这个问题研究清楚. (一)普通案例 下面从一个普通的案例入手,下面准备两个List集合,都是放在内存里面的(需要模拟到远端执行的时候,我们是通 ...

  8. [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门

    [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习 ...

  9. [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用

    [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用 本节导读:讨论了表达式树的定义和解析之后,我们知道了表达式树就是并非可执行代码,而是将表达式对象化后的数据结构.是 ...

随机推荐

  1. EXCEL IF 函数 模糊查询

    A列都是产品名,比如衬衫,长袖衬衫,短袖衬衫,短裙,长裙 搜索A列的产品名,凡是含有“衬衫”的一律在B列对应行输出“衬衫”,凡是含有“裙”字的一律输出“裙子”在B列对应行,请教一下怎么写函数,本来用I ...

  2. Android 开发框架

    Android 开发框架包括基本的应用功能开发.数据存储.网络访问三大块. 1 应用方面 一般而言,一个标准的Android 程序包括Activity.Broadcast Intent Receive ...

  3. [嵌入式学习资料]ARM开发学习详解iTOP-4412开发板使用手册

    拿到的最新4412开发板学习使用手册,完全免费,分享一下 下载地址:http://pan.baidu.com/s/1ntrJA8h

  4. SOS: gnuplot fdtd的一个问题求助 perl vs python

    我用perl和python写了相同功能的一段程序,计算一维fdtd,用gnuplot动态显示,可是python的数据没有显示出来,看横纵坐标的变化数据是正确收到了的,如最后的图片,求大神指点,谢谢. ...

  5. [转]关于负margin在页面中布局的应用

    本文转载自:http://www.cnblogs.com/jscode/archive/2012/08/28/2660078.html. 今天再写一个布局的时候用到一个margin-top是负值的情况 ...

  6. 前端MVC学习总结(四)——NodeJS+MongoDB+AngularJS+Bootstrap书店示例

    这章的目的是为了把前面所学习的内容整合一下,这个示例完成一个简单图书管理模块,因为中间需要使用到Bootstrap这里先介绍Bootstrap. 示例名称:天狗书店 功能:完成前后端分离的图书管理功能 ...

  7. js模拟手机触摸屏

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  8. getBoundingClientRect详解

    getBoundingClientRect获取的left和top始终是该元素相对于页面原点坐标的位置,当它大于原点坐标则为正数,等于原点坐标为零,小于为负数.

  9. Maven 其他功能

    测试:指定测试哪些测试类,指定哪些测试类不测试,可以使用通配符 使用 Hudson 进行持续集成 持续集成:快速且高频率地自动构建项目的所有源码,并为项目成员提供丰富的反馈信息 一个典型的持续集成场景 ...

  10. 【转】【PNG压缩工具】PNG 图像的优化及压缩工具介绍

    图像格式有许多种不同类型,在互联网上最常见的有JPEG.GIF.BMP.TIFF和PNG.每一种图像格式都有它自己的用途,比如GIF是用于动画的,JPEG是用于高清图片的,这种图片在保存或者调整大小后 ...