C# Lambda Expressions 简介
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 简介的更多相关文章
- jdk8新特性之lambda expressions
本文分两部分: 语法简单说明 lambda的使用 注:这两部分内容均以类+注释的方式进行说明,并且内容均来自官方教程(https://docs.oracle.com/javase/tutorial/j ...
- java语言中的匿名类与lambda表达式介绍与总结 (Anonymous Classes and Lambda Expressions)
2017/6/30 转载写明出处:http://www.cnblogs.com/daren-lin/p/anonymous-classes-and-lambda-expressions-in-java ...
- 1.8 新特性之 Lambda Expressions
Lambda expressions are allowed only at source level 1.8 or above The target type of this expression ...
- lambda expressions are not supported at this language level
IDEA下报错:lambda expressions are not supported at this language level 解决: 1. File -> Project Struct ...
- ef中用lambda expressions时要注意(m=>m.id ==b ) 此时的b只能是基本的数据类型 。连属性都不能用
ef中用lambda expressions时要注意(m=>m.id ==b ) 此时的b只能是基本的数据类型 .连属性都不能用
- Hacking Lambda Expressions in Java
Hacking Lambda Expressions in Javahttps://dzone.com/articles/hacking-lambda-expressions-in-java At t ...
- 【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 ...
- AS报错:lambda expressions are not supported at this language level
AS报错:lambda expressions are not supported at this language level 解决方法 打开打开 File --> Project Stuct ...
- 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 ...
随机推荐
- jquery里用each遍历的值存到数组和字符串
$("img").each(function(){ var a = $(this).attr("src"); }); //遍历后存放到数组中..要用的时候再根据 ...
- 2015年最新出炉的JavaScript开发框架
前端框架简化了开发过程中,像 Bootstrap 和 Foundation 就是前端框架的佼佼者.在这篇文章了,我们编制了一组新鲜的,实用的,可以帮助您建立高质量的 Web 应用程序的 JavaScr ...
- 8个web前端的精美HTML5 & CSS3效果及源码下载
作为一个前沿的 Web 开发者,对于 HTML5 和 CSS3 技术或多或少都有掌握.前几年这些新技术刚萌芽的时候,开发者们已经使用它们来小试牛刀了,如今这些先进技术已经遍地开发,特别是在移动端大显身 ...
- 杭电ACM2061--Treasure the new start, freshmen!
http://acm.hdu.edu.cn/showproblem.php?pid=2061 这题很简单.注意换行. <span style="font-size:18px;" ...
- 9.配置postfix空客户端
将本地邮件服务器配置充当为控客户端,已将所有邮件都转发到中央服务器以进行发送 1.postconf -e "relayhost=[mail.example.com]" 邮件被路由到 ...
- Bundle、Intent、SharedPreferences
Intent与Bundle的共同点:都继承Parcelable Intent传值与Bundle传值的区别 eg:我现在要从A界面 跳转到B界面或者C界面 这样的话 我就需要写2个Intent ...
- AngularJS(17)-Angular小程序
现在可以开始创建您的第一个 AngularJS 应用程序,一个 AngularJS 单页 Web 应用. <!DOCTYPE html> <html lang="en&qu ...
- C# 实例化接口对象
在head first 设计模式中 用到了很多很多接口对象 首先澄清一个问题,就是接口不仅可以声明对象,而且可以把对象实例化,还可以当做参数被传入. 一.接口回调 这就是继承中的向上转型.父类 FL= ...
- DataTable中如何去除重复的项【转】
上周在项目中遇到一个问题,就是获取DataTable中某一列的值,因为从数据库中检索数据时,按照2个字段进行分组,而要获得的那一列刚好在分组这两列中,所以该列的值必然有重复,于是就想到了去除重复,有了 ...
- Ubuntu下Code::Blocks无法编译 /bin/sh: 1: g++ not found 解决办法
Linux下Code::Blocks无法编译运行提示 /bin/sh: 1: g++ not found 的解决办法 今天在Ubuntu 12.04 软件中心中选装了Code::Blocks,安装完成 ...