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. javaScript之 变量、作用域和内存问题

    <javaScript高级程序设计>第四章  读书笔记 4.1  基本类型 和 引用类型 的值 1. 基本类型值 包括:Undefined.Null.Boolean.Number 和 St ...

  2. HDU1070 Milk 细节决定成败

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1070 注意:1.喝到第五天,第六天就不喝了  2.相同花费的,优先考虑容量大的  3.注意强制类型转换 ...

  3. 洛谷 P3374 【模板】树状数组 1

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  4. 【NPOI】.NET EXCEL导入导出开发包

    1.导出 //工作簿HSSFWorkbook HSSFWorkbook hssfworkbook = new HSSFWorkbook(); //ISheet页 ISheet sheet1 = hss ...

  5. shell脚本初识

    #!/bin/bash(linux脚本环境的声明即解释器,该解释器为bash,位于根目录下的bin目录下) 变量的定义与赋值: 格式:变量名=变量值(无需声明变量类型) 变量的引用: 格式:$变量名 ...

  6. c#获取今天星期几

    System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.GetDayName(DateTime.Now.DayOfWeek)

  7. php更新修改excel中的内容例子

    代码如下 复制代码 //模板存放目录$dir = $DOCUMENT_ROOT.'/backoffice/admin/oemcheck/';  $templateName = '1.xlsx';$ou ...

  8. 防DDOS攻击

    /ip firewall filter add chain=forward connection-state=new action=jump jump-target=block-ddos add ch ...

  9. How to check Windows 7 OS is permanently activated?[Windows 7]

    Press Windows + R, then you can enter : slmgr.vbs -xpr

  10. Mysql数据库中的计数器表实时更新

    如果某个应用中存在计数器,例如网站的总访问量.用户的粉丝数.文件下载数等等.如果相关应用在Mysql数据库的表中保存计数器,在更新计数器的时候可能会碰到并发问题.例如在web应用中,记录网站的点击次数 ...