学习自

《C#本质论》

Overview

在上一文中,我们简而又简的了解了一下,匿名方法和Lambda表达式,关于匿名方法这里暂且不表,本文我们来更加详细的了解一下Lambda表达式。

本文涉及到了大量的LInq方面的知识,如果看官你还没有接触到Linq那么本章可以略过。

语句Lambda和表达式Lambda

语句Lambda , 从语义上可以简单的理解为,一个语句块的委托。

比如说类似这样的,有多条语句组成的Lambda,被称为 语句Lambda

(x) =>{

    int value =0;
for(int i =0 ; i<x ; i ++ ){
value+=1;
}
return value;
}

表达式 Lambda , 从语义上理解就是只有返回的表达式没有语句块。

比如说下面的,如果你接触过 Linq那么你一定很熟悉这种方式。

var result = persons.Where(t=>t.Name=="hello");

这么看起来没有什么特别显著的区别,请继续向下看。

表达式树(Expression tree)

语句Lambda和表达式Lambda最后的生成的结果,是完全不同的,一个语句Lambda将会生成一个委托,而一个表达式Lambda既可以生成一个委托,也可以转换为表达式树(expression tree)。 表达式树是一个对象,允许编译器对Lambda表达式的保主体进行分析。

在ORM框架中常常会见到类似这样的代码

var result = db.Persons.Where(t=> t.Name=="Hello");

假设Person是数据库中的一个表 假设表中有大概10w条数据,然后我们要再这个表中找到 Name = 'Hello' 的Person

当我们执行查询的时候,有两个解决思路

  • 将数据库所有的数据都返回给客户端,然后客户端为灭一条记录创建一个对象,形成一个集合,然后我们通过定义的委托,来判断是否是我们需要的对象,如果是我们需要的对象那么拿出来,其他的对象丢弃掉。这种方式理论上是可行的,但是,从一个数据表中插叙1条或者几条记录,就要将所有的数据都吃进内存中,后果可想而知,所以这种方式可想而知。
  • 第二个解决思路, 将我们“Lambda” 发送给您服务器数据库,然后让服务器数据库进行过滤操作,然后我们仅仅拿到符合我们的结果的几条数据。这种方式使我们ORM所通用的解决思路。

当然仅仅直接将我们是Lambda表达式发送给数据库,显然是不行的,所以我们要在中间做一层转换,将我们的Lambda表达式转换为描述Lambda描述的对象表达式树 ,而不是一个编译好的一个匿名函数的代码。应为表达式数代表着是数据而不是编译好的代码,所我们能在运行的时候去分析Lambda,在ORM框架中就将 Where() 方法中接收到的表达式树转换为Sql查询语句 交给数据库去执行,并返回我们需要的数据。

转换如下:

NOTE: 表达式不是仅仅只能转换为sql语句,而是通过一个表达式树计算程序(evaluator) ,将表达式转换为任意的查询语言。

语句Lambda和表达式Lambda是如何区分的

不管是将Lambda转换为委托哈市表达式树,一个Lambda表达式都会在编译时进行全面的语义解析,如果是转换为委托,那么就会将这个Lambda 生成为一个方法,并创建委托。但是在使用Linq的时候明显不是这样的,编译器是如何判断一个Lambda该如何处理?生成委托,还是生成表达式树?

这里将以Where方法为例子,进行讲解。

利用Where方法查询集合:

static List<Person> personList = new List<Person>
{
new Person() { Name="1", Gender="Male", Age="12"},
new Person() { Name="2", Gender="Male", Age="12"},
new Person() { Name="3", Gender="Male", Age="12"},
};
static void Main(string[] args)
{
personList.Where(t => t.Name.Equals("1"));
}

F12转到Where方法的定义 , 我们发现他是一个IEnumerable 泛型的 的扩展方法。

        public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

看一下反编译

在这里是生成了委托。

LINQ 中的Where方法,

 static void Main(string[] args)
{
DBDataContext db = new DBDataContext();
var result = db.Roles.Where(t => t.RoleName == "TestRole");
}

是IQueryable 接口的扩展方法

    public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);

查看一下反编译,没有生成委托,而是生成了一个 Linq 表达式。

  • 当Where() 方法的调用者能够隐式转换为 IEnumerable 类型时,Lambda表达式将会生成委托
  • 当Where() 方法的调用者能够隐式转换为IQueryable 类型时,Lambda表达式将会生成表达式树

结语

说实话,本文确实不太好,强烈推荐大家去看一下,原文,本文是《C#》本质论的学习笔记。

Lambda的分类(语句Lambda和表达式Lambda)的更多相关文章

  1. (转) Lambda表达式中的表达式lambda和语句lambda区别

    Lambda表达式可分为表达式lambda和语句lambda 表达式lambda:表达式位于 => 运算符右侧的lambda表达式称为表达式lambda (input parameters) = ...

  2. Lambda表达式中的表达式lambda和语句lambda区别

    Lambda表达式可分为表达式lambda和语句lambda 表达式lambda:表达式位于 => 运算符右侧的lambda表达式称为表达式lambda (input parameters) = ...

  3. Lambda表达式(lambda expression)⭐⭐⭐⭐⭐

    原作者 lambda表达式(lambda expression)实际上是匿名函数一种表示形式, 即没有函数名的函数:参数列表=>表达式或语句块,在我看来主要目是为了简化代码编写,提高代码可读性而 ...

  4. Python中特殊函数和表达式lambda,filter,map,reduce

    1.lambda:使用lambda表达式可以定义一个匿名函数 lambda表达式是一种简洁格式的函数.该表达式不是正常的函数结构,而是属于表达式的类型 (1)基本格式: lambda 参数,参数... ...

  5. Python学习教程(learning Python)--3.3 分支语句的条件表达式详解

    本节主要讨论分支语句的条件表达式问题. 在if或者if-else分支控制语句里由于都用到条件判断(表达式是真还是假),条件判断可以是一种关系运算也可以是布尔表达式. 本节将对if及if-else语句的 ...

  6. SQL 无限级分类语句

    原文:SQL 无限级分类语句 原表数据为: 此处用到了with关键字,在程序中也可以用递归实现,但觉得还是没有一条sql方便 with tb (ID,Name,ParentID,Sort) as( s ...

  7. day3_python之函数返回值、语句形式、表达式形式

    一. 函数对象 1. 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素 二.返回值 return的返回值没有类型 ...

  8. 点标记(lambda表达式+linq查询标记符)与linq语句(查询表达式)

    什么是Linq表达式?什么是Lambda表达式? 参照:https://www.cnblogs.com/zhaopei/p/5746414.html

  9. Java基础进阶:内部类lambda重点摘要,详细讲解成员内部类,局部内部类,匿名内部类,Lambda表达式,Lambda表达式和匿名内部类的区别,附重难点,代码实现源码,课堂笔记,课后扩展及答案

    内部类lambda重点摘要 内部类特点: 内部类可以直接访问外部类,包括私有 外部类访问内部类必须创建对象 创建内部对象格式: 外部类.内部类 对象名=new外部类().new内部类(); 静态内部类 ...

随机推荐

  1. C#创建基本图表(Chart Controls)

    在.NET环境下微软提供了强大了图表控件,并给多了很多实例,关于图表的基本元素如下: 并且MSDN给出了创建图表的示例步骤,原文地址:http://msdn.microsoft.com/en-us/l ...

  2. Hadoop生态圈-Kafka的本地模式部署

    Hadoop生态圈-Kafka的本地模式部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Kafka简介 1>.什么是JMS 答:在Java中有一个角消息系统的东西,我 ...

  3. Hadoop生态圈-Flume的主流source源配置

    Hadoop生态圈-Flume的主流source源配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客只是配置的是Flume主流的Source,想要了解更详细的配置信息请参 ...

  4. freemark+ITextRenderer 生成PDF,设置pdf的页面大小

    在html中添加样式,仅生成pdf是生效,浏览器展示时是不会生效的: <style> @page{ size : 200mm  300 mm;   } </style>

  5. nova-api源码分析(APP的创建)

    目录结构如下: 上面介绍了nova-api发布所用到的一些lib库,有了上面的基础知识,再来分析nova-api的发布流程,就比较轻松了.nova-api可以提供多种api服务:ec2, osapi_ ...

  6. Java SSM框架之MyBatis3(六)MyBatis之参数传递

    一.单个参数  StudentParamsMapper package cn.cnki.ref.mapper; import cn.cnki.ref.pojo.Student; public inte ...

  7. ubuntu 环境下pycharm的 安装与激活教程 以及错误解决方法

    1. 基本安装: 1.1 打开Ubuntu的应用市场,并在搜索栏搜索pycharm,结果如下图所示 1.2 选择pro版本进行安装,结果如下图所示: 1.3打开安装后的pycharm,如果出现下图所示 ...

  8. python 基础 元组()

    # 元组 应用场景 # 尽管 Python的列表中可以存储不同类型的数据 # 但是在开发中,更多的应用场景是 # 1.列表存储相同类型的数据 # 2.通过迭代遍历,在循环体内部,针对列表中的每一项元素 ...

  9. css框架,一把锋利的剑

    CSS 框架是一系列 CSS 文件的集合体,包含了基本的元素重置,页面排版.网格布局.表单样式.通用规则等代码块,用于简化web前端开发的工作,提高工作效率. 产生原因 互联网行业已经发展了多年,浏览 ...

  10. javascript的单例/单体模式(Singleton)

    首先,单例模式是对象的创建模式之一,此外还包括工厂模式.单例模式的三个特点:1,该类只有一个实例2,该类自行创建该实例(在该类内部创建自身的实例对象)3,向整个系统公开这个实例接口 Java中大概是这 ...