C# Lambda Expressions 简介

原文http://msdn2.microsoft.com/en-us/library/bb397687.aspx

翻译:朱之光 (larry1zhu@gmail.com)

1.  Lambda简介

一个Lambda Expression  (译为Lambda式) 就是一个包含若干表达式和语句的匿名函数。可以被用作创建委托对象或表达式树类型。

所有的Lambda式都使用操作符“=>“,表示“goes to (转变为)”。操作符左边部分是输入参数表,右边部分是表达式或语句块。x => x * x 读成“x转变为x 乘x”。

Lambda式可以被赋值给一个委托类型:

例1

delegate int del(int i);

del myDelegate = x => x * x;

int j = myDelegate(5); //j = 25

也可以被用于创建一个表达式树类型:

例2

using System.Linq.Expressions;

//…

Expression<del> = x => x *x;

操作符“=>”具有和“=”一样的运算优先级,且为右相关(右边先执行)。

在例1中,我们注意到委托的定义中有一个int类型的输入参数以及int类型的返回值。例子中的Lambda式中并没有任何类型的声明。是编译器为我们做了相应的隐式数据类型转换:输入参数类型能够从委托的输入参数类型隐式转换,返回类型能够被隐式转换为委托的返回类型。

Lambda式不允许作为“is”和“as”操作符的左操作数出现。也就是

del myDelegate = x => x * x as string;      //error

所有对于匿名方法的约束也同样适用于Lambda式。请参阅Anonymous Methods (C# Programming Guide).

2.  表达式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内执行。

一般来说,让一个方法在原先设计的上下文环境以外执行没有意义,也不能真正工作。

3.  语句Lambda

语句Lambda和表达式Lambda非常相似,只是语句被包含在大括号内:

(input parameters) => {statement;}

大括号中的语句可以是任意多条,也可以写成多行(定义一个Lambda式也就是在定义一个匿名方法):

TestDelegate myDel = n => { string s = n + " " + "World";

Console.WriteLine(s); };

当然语句Lambda跟匿名方法一样,无法用于创建表达式树。

4.  类型猜测

当编写一个Lambda式的时候,我们通常不需要明确指定输入参数的类型。因为编译器会根据Lambda体的实现,以及委托的定义来猜测类型。

举例:如果要从一个List<int>中删除小于100的元素

lst.RemoveAll(i => i < 100);       //i会被猜测为int

通常的猜测规则如下:

  • Lambda式必须包含与委托定义中相等数量的输入参数;
  • 每个Lambda式的输入参数必须能够隐式转换成委托定义中所要求的输入参数;
  • Lambda式的返回值必须能够隐式转换成委托定义中的返回值。

注意:由于目前在common type system中还没有一个“Lambda式类型”的类型。如果在有些场合提到“Lambda式的类型”,那通常表示委托的定义或者是Expression<>类型。

5.  Lambda中的变量作用域

在Lambda式定义中可以引用外部变量。只要是在定义处能够访问到的变量,都可以在Lambda式中引用。

Lambda式的定义仅仅是定义一个匿名方法,最终会生成一个委托对象。外部变量的引用将被“捕获”到委托对象内部,将会伴随委托对象的整个生命周期。在委托对象生命周期结束之前该变量都不会被垃圾回收。就算外部变量已经超过了原来的作用域,也还能继续在Lambda式中使用。所有会被引用的外部变量必须在Lambda式定义之前被显式赋值。见下例

    delegate bool D();
delegate bool D2(int i); class Test
{
D del;
D2 del2; public void TestMethod(int input)
{
int j = ;
// Initialize the delegates with lambda expressions.
// Note access to 2 outer variables.
// del will be invoked within this method.
del = () => { j = ; 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.
bool boolResult = del(); // Output: j = 10 b = True
//注意j在del的执行过程中被修改
Console.WriteLine("j = {0}. b = {1}", j, boolResult);
} static void Main()
{
Test test = new Test();
test.TestMethod(); // Prove that del2 still has a copy of
// local variable j from TestMethod.
//j的引用超出了原先定义的作用域
bool result = test.del2(); // Output: True
Console.WriteLine(result);
Console.ReadKey();
}
}

作用域

下面是关于变量作用域的规则:

  • 被“捕获”的变量在委托的生命周期结束前都不会被垃圾回收;
  • 在Lambda式内部定义的变量对外不可见;
  • Lambda式无法直接捕获一个具有ref或out描述的参数变量;
  • Lambda式中的return语句不会导致当前所在的方法返回;
  • Lambda式中不允许包含会导致跳当前执行范围的goto,break 或 continue语句。

     6.  总结

Lambda式可以说就是另外一种形式的匿名方法。用在某些地方,会使代码更加简洁。

定义一个Lambda式本质上就是定义一个委托的实现体。

C# Lambda Expressions 简介的更多相关文章

  1. jdk8新特性之lambda expressions

    本文分两部分: 语法简单说明 lambda的使用 注:这两部分内容均以类+注释的方式进行说明,并且内容均来自官方教程(https://docs.oracle.com/javase/tutorial/j ...

  2. java语言中的匿名类与lambda表达式介绍与总结 (Anonymous Classes and Lambda Expressions)

    2017/6/30 转载写明出处:http://www.cnblogs.com/daren-lin/p/anonymous-classes-and-lambda-expressions-in-java ...

  3. 1.8 新特性之 Lambda Expressions

    Lambda expressions are allowed only at source level 1.8 or above The target type of this expression ...

  4. lambda expressions are not supported at this language level

    IDEA下报错:lambda expressions are not supported at this language level 解决: 1. File -> Project Struct ...

  5. ef中用lambda expressions时要注意(m=>m.id ==b ) 此时的b只能是基本的数据类型 。连属性都不能用

    ef中用lambda expressions时要注意(m=>m.id ==b ) 此时的b只能是基本的数据类型 .连属性都不能用

  6. Hacking Lambda Expressions in Java

    Hacking Lambda Expressions in Javahttps://dzone.com/articles/hacking-lambda-expressions-in-java At t ...

  7. 【104】Maven3.5.0结合eclipse使用,提示Lambda expressions are allowed only at source level 1.8 or above错误的解决方法

    错误重现 我的机器上安装了 maven 3.5.0,在 eclipse 中创建 maven 项目.pom.xml配置如下: <project xmlns="http://maven.a ...

  8. AS报错:lambda expressions are not supported at this language level

    AS报错:lambda expressions are not supported at this language level 解决方法 打开打开 File --> Project Stuct ...

  9. Lambda Expressions and Functional Interfaces: Tips and Best Practices

    转载自https://www.baeldung.com/java-8-lambda-expressions-tips 1. Overview   Now that Java 8 has reached ...

随机推荐

  1. DFS入门之二---DFS求连通块

    用DFS求连通块也是比较典型的问题, 求多维数组连通块的过程也称为--“种子填充”. 我们给每次遍历过的连通块加上编号, 这样就可以避免一个格子访问多次.比较典型的问题是”八连块问题“.即任意两格子所 ...

  2. curl raise 信号出core

    在使用c++多线程使用libcurl抓取网页时,遇到程序随机core掉的情况,gdb 一下出错信息有这么一条:longjmp causes uninitialized stack frame. 在网上 ...

  3. Windows Phone 7 ListBox 列表项渐显加载动画学习笔记

    在wp7程序中,当程序功能越来越复杂时,性能问题是我们不得不考虑的一个问题.在聊天列表中,如果聊天项过多,而且项目UI组件足够复杂时, 我们不得不想尽办法让UI尽快加载.所以有一种可行的方案,就是像Q ...

  4. 《samba服务配置的文本》

    创建简单的samba服务器 samba  很少用于互联网 /大部分用于局域网  网页更新/ 首先看下你是否安装后了samba. rpm -qa | grep samba samba的简介 1)samb ...

  5. hover和mouseover,mouseout的区别

    说道hover和mouseover,mouseout的区别,不得不联系到mouseenter,mouseleave. mouseover,mouseout是指鼠标指针在穿过/离开被选元素或其子元素时触 ...

  6. 解析php开发中的中文编码问题

    其实php开发中的中文编码并没有想像的那么复杂,虽然定位和解决问题没有定规,各种运行环境也各不尽然,但后面的原理是一样的. 了解字符集的知识是解决字符问题的基础. PHP程序设计中中文编码问题曾经困扰 ...

  7. css透明(支持各浏览器)

    opacity: 0.4;filter: progid:DXImageTransform.Microsoft.Alpha(opacity=40); -ms-filter: "progid:D ...

  8. 【面试虐菜】—— Jboss调优

    吐血整理了以前Jboss以及JVM在生产环境下的调优参数,各种不同的案例,都是来自网友杜撰.整合后,希望对广大使用jboss作为生产应用服务器的朋友有所帮助. JBOSS参数调优 配置deploy/j ...

  9. HDU 2669 第六周 I题

    Description The Sky is Sprite.  The Birds is Fly in the Sky.  The Wind is Wonderful.  Blew Throw the ...

  10. Ubuntu中NetBeans C/C++配置、编译

    系统环境:Ubuntu 9.04软件环境:NetBeans 6.7.1 C/C++ .JDK1.6.0_16本次目的:完成NetBeans 6.7.1 C/C++ 的配置工作.编译测试及对中文支持 首 ...