一.简介
一个Lambda Expression(译为Lambda式)就是一个包含若干表达式和语句的匿名函数。可以被用作创建委托对象或表达式树类型。Lambda表达式对于编写 LINQ 查询表达式特别有用。
所有的Lambda式都使用操作符“=>“,表示“goes to (转变为)”。操作符左边部分是输入参数表,右边部分是表达式或语句块。接下来就看一下它的作用及用法。
二.何时用?
在Framework 2.0 以前,声明委托的唯一方法是通过方法命名,从Framework 2.0 起,系统开始支持匿名方法。
通过匿名方法,可以直接把一段代码绑定给事件,因此减少了实例化委托所需的编码系统开销。
而在 Framework 3.0 开始,Lambda 表达式开始逐渐取代了匿名方法,作为编写内联代码的首选方式。总体来说,Lambda 表达式的作用是为了使用更简单的方式来编写匿名方法,彻底简化委托的使用方式。
那么接下来就通过几个实例来理解一下吧!
用匿名方法
static void Main(string[] args)
{
Button btn = new Button();
btn.Click+=delegate(objectobj,EventArgs e){
MessageBox.Show("HelloWorld !");
};
}
使用Lambda表达式
- <span style="font-size:18px;">static void Main(string[] args)
- {
- Button btn = new Button();
- btn.Click+=(object obj,EventArgs e)=>{
- MessageBox.Show("Hello World !");
- };
- }
- </span>
通过以上对匿名函数和Lambda表达式的实战是否发现Lambda表达式其实就是一个匿名函数,但是它比匿名函数更容易让人理解,更简单,这也是它近年来发展迅速的原因吧!接下来就针对Lambda表达式来讲解一下。
三.表达式用法
1.表达式Lambda
由一个计算表达式组成的一个Lambda式称之为表达式Lambda。表达式Lambda常被用于构造表达式树。一个表达式Lambda返回计算表达式运算的结果。
基本结构:
(input parameters)=> expression
如果只有一个输入参数时,括号可以省略。如果具有一个以上的输入参数,必需加上括号。
(x) => x * x 等于 x => x * x
(x, y) => x ==y
可以显式指定输入参数的类型
(int x, string s)=> s.Length > x
也可以没有任何输入参数
() =>SomeMethod1()
上面这段代码在Lambda式中调用了一个方法。需要注意的是,如果在创建会被其他方使用的表达式树的时候,不宜在Lambda式中执行方法调用。比如:在SQL Server内执行。
一般来说,让一个方法在原先设计的上下文环境以外执行没有意义,也不能真正工作。
2.语句Lambda
语句Lambda和表达式Lambda非常相似,只是语句被包含在大括号内:
(input parameters)=> {statement;}
大括号中的语句可以是任意多条,也可以写成多行(定义一个Lambda式也就是在定义一个匿名方法):
TestDelegate myDel= n => { string s = n + " " + "World";
Console.WriteLine(s);};
当然语句Lambda跟匿名方法一样,无法用于创建表达式树。
3.类型猜测
当编写一个Lambda式的时候,我们通常不需要明确指定输入参数的类型。因为编译器会根据Lambda体的实现,以及委托的定义来猜测类型。
举例:如果要从一个List<int>中删除小于100的元素
Llst.RemoveAll(i=> i < 100);//i会被猜测为int
通常的猜测规则如下:
1. Lambda式必须包含与委托定义中相等数量的输入参数;
2. 每个Lambda式的输入参数必须能够隐式转换成委托定义中所要求的输入参数;
3.Lambda式的返回值必须能够隐式转换成委托定义中的返回值。
注意:由于目前在common type system中还没有一个“Lambda式类型”的类型。如果在有些场合提到“Lambda式的类型”,那通常表示委托的定义或者是Expression<>类型。
4.Lambda式中的变量作用域
在Lambda式定义中可以引用外部变量。只要是在定义处能够访问到的变量,都可以在Lambda式中引用。
Lambda式的定义仅仅是定义一个匿名方法,最终会生成一个委托对象。外部变量的引用将被“捕获”到委托对象内部,将会伴随委托对象的整个生命周期。在委托对象生命周期结束之前该变量都不会被垃圾回收。就算外部变量已经超过了原来的作用域,也还能继续在Lambda式中使用。所有会被引用的外部变量必须在Lambda式定义之前被显式赋值。见下例
delegatebool D();
delegatebool D2(int i);
classTest
{
Ddel;
D2del2;
publicvoid TestMethod(int input)
{
intj = 0;
//Initialize the delegates with lambda expressions.
//Note access to 2 outer variables.
//del will be invoked within this method.
del= () => { j = 10;return j > input; };
//del2 will be invoked after TestMethod goes out of scope.
del2= (x) => {return x == j; };
//Demonstrate value of j:
//Output: j = 0
//The delegate has not been invoked yet.
Console.WriteLine("j= {0}", j);
//Invoke the delegate.
boolboolResult = del();
//Output: j = 10 b = True//注意j在del的执行过程中被修改
Console.WriteLine("j= {0}. b = {1}", j, boolResult);
}
staticvoid Main()
{
Testtest = new Test();
test.TestMethod(5);
//Prove that del2 still has a copy of
//local variable j from TestMethod. //j的引用超出了原先定义的作用域
boolresult = test.del2(10);
//Output: True
Console.WriteLine(result);
Console.ReadKey();
}
}
下面是关于变量作用域的规则:
1.被“捕获”的变量在委托的生命周期结束前都不会被垃圾回收;
2.在Lambda式内部定义的变量对外不可见;
3. Lambda式无法直接捕获一个具有ref或out描述的参数变量;
4.Lambda式中的return语句不会导致当前所在的方法返回;
5.Lambda式中不允许包含会导致跳当前执行范围的goto,break或 continue语句。
四.总结
Lambda式可以说就是另外一种形式的匿名方法。用在某些地方,会使代码更加简洁。定义一个Lambda式本质上就是定义一个委托的实现体。
相关推荐
1. Lambda表达式基础: Lambda表达式在C#中的语法形式为 `(参数列表) => 表达式` 或 `(参数列表) => { 函数体 }`。这里的参数列表可以为空,表达式则代表函数的计算结果。如果只有一个参数,圆括号可以省略。例如,...
在本篇文章中,我们将深入探讨如何使用Linq To EF结合Lambda表达式进行数据库操作。 首先,为了开始使用Linq To EF,我们需要创建一个数据库实体对象。在示例中,我们创建了一个名为`DbTrainEntities`的对象: ```...
在这篇教程里,我们将要去了解下即将到来的JDK 8(译注,现在JDK 8已经发布了)中的Lambda表达式——特别是怎样使用它来编写Comparator和对集合(Collection)进行排序。 这篇文章是Baeldung上的“Java ——...
本篇文章将深入探讨其中三个关键特性:Lambda表达式、函数式接口以及接口中的默认方法和静态方法。 首先,Lambda表达式是Java8的核心特性之一,它允许我们以一种更简洁的方式表示匿名函数。在之前的版本中,如果...
本篇将详细解读Java8的关键新特性,包括Lambda表达式、函数式接口、Stream API、日期时间API的改进以及Optional类的引入。 首先,Lambda表达式是Java8引入的最重要的特性之一。Lambda表达式可以理解为匿名函数,它...
本篇将对JDK8中引入的几个关键特性进行详细介绍,包括默认方法与静态方法的引入、函数式接口的定义和使用、Lambda表达式的引入以及内置功能接口的应用等。 首先,JDK8允许在接口中定义默认方法和静态方法。默认方法...
本篇文章将深入探讨如何利用C#中的Lambda表达式和EF框架来操作SQL数据库。 首先,要使用EF,你需要在项目中引入`Microsoft.EntityFrameworkCore`和`Microsoft.EntityFrameworkCore.SqlServer` NuGet包。这些包提供...
8. **Lambda表达式**:函数式编程的概念,Lambda的使用,以及Stream API。 9. **模块化系统**:Java 9引入的模块系统,模块化的好处,模块间的依赖关系。 10. **并发编程**:Executor框架,Future和Callable接口,...
Java语言程序设计基础篇是学习Java编程的入门教材,原书第8版的复习题答案对于正在学习这门课程的学生来说具有极高的参考价值。Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems(现为Oracle公司)开发...
Java语言程序设计(基础篇)是一本针对初学者编写的教程,旨在帮助读者掌握Java编程的基础知识。这个压缩包很可能包含了书中的章节内容、代码示例以及可能的课后习题,是学习Java语言的理想资源。 Java语言设计的...
15. **Lambda表达式**:简化函数式编程,用于创建匿名函数和简化处理集合的操作。 通过学习Java的基础篇和进阶篇,你将具备编写高效、健壮的Java应用程序的能力,为未来在IT行业的职业生涯打下坚实的基础。
函数式编程是Python的一大特色,你将学习到高阶函数如map、filter、reduce的使用,以及lambda表达式和闭包的概念。这些工具可以帮助你写出更高效、更简洁的代码。 面向对象编程(OOP)在Python中也得到了很好的支持...
首先,JDK 8是Java Development Kit的一个重大更新,其中最显著的变化就是增加了lambda表达式。Lambda表达式使得函数式编程风格在Java中变得更为简洁,它允许我们将函数作为一个对象进行传递,简化了多线程和事件...
首先,JDK 1.8引入了Lambda表达式,这是Java语言的重大改进,它简化了处理函数式编程场景。Lambda允许开发者用更简洁的方式表示匿名函数,减少了代码量,提高了代码的可读性和可维护性。例如,可以使用lambda表达式...
本文档总结了经典 Python 面试题之 Python 基础篇的知识点,涵盖了 Python 基础知识、数据类型、运算符、控制结构、函数、模块、文件操作、异常处理、正则表达式、面向对象编程等方面的重要概念和技术细节。...
除了Lambda表达式,JDK 8还引入了方法引用,它可以更直接地引用已有的方法,而不是用Lambda表达式来重写。这使得代码更加清晰和简洁。 ### 5. **默认方法** 在接口中添加默认方法是JDK 8的一个重要特性,它允许在不...
JDK 1.8引入了Lambda表达式,这是一种简洁的匿名函数表示方式,它允许将函数作为一个值传递。Lambda表达式极大地简化了多参数和单语句的函数式接口实现,提高了代码的可读性和简洁性。 2. **方法引用和构造器引用*...
- **Lambda表达式基础**:介绍Lambda表达式的语法特点,以及如何使用它们简化代码。 - **函数式接口与方法引用**:了解Predicate、Function等函数式接口的作用,以及方法引用这种更简洁的Lambda表达式写法。 - **流...
2. **函数接口**: Java 8引入了`@FunctionalInterface`注解,使得函数接口(只有一个抽象方法的接口)成为核心概念,是Lambda表达式的基础。 3. **Stream API**: Stream API提供了对集合数据进行操作的新方式,支持...
首先,JDK 1.8引入了Lambda表达式,这是一种简洁的函数式编程语法,极大地简化了处理集合和多线程的操作。Lambda表达式允许开发者以匿名函数的形式传递代码,使得代码更加简洁、易读,尤其是在处理高阶函数时。例如...