C#中Lambda表达式的用法
作者:Ruby_Lu 发布时间:2022-07-29 17:29:56
从C#3.0开始,可以使用lambda表达式把实现代码赋予委托。lambda表达式与委托(https://www.jb51.net/article/244051.htm)直接相关。当参数是委托类型时,就可以使用lambda表达式实现委托引用。
static void Main()
{
string mid = ", middle part,";
Func<string, string> anonDel = param =>
{
param += mid;
param += " and this was added to the string.";
return param;
};
Console.WriteLine(anonDel("Start of string"));
}
lambda运算符“=>” 的左边是参数列表,右边是lambda变量的方法的实现代码。
1.参数
如果lambda表达式只有一个参数,只写出参数名就可以,像上面的代码。
如果委托使用多个参数,就需要把参数名放到括号中:
Func<double, double, double> twoParams = (x, y) => x * y;
Console.WriteLine(twoParams(3, 2));
可以在括号中给变量名添加参数类型:
Func<double, double, double> twoParamsWithTypes = (double x, double y) => x * y;
Console.WriteLine(twoParamsWithTypes(4, 2));
2.多行代码
如果lambda表达式只有一条语句,在方法块内就不需要花括号和return语句,因为编译器会添加一条隐形的return语句。
Func<double, double, double> twoParams = (x, y) => x * y;
Func<double, double, double> twoParams = (x, y) =>
{
retrun x * y;
}
如果在lambda表达式的实现代码中有多条语句,就必须添加花括号和return语句:
Func<string, string> anonDel = param =>
{
param += mid;
param += " and this was added to the string.";
return param;
};
3.闭包
通过lambda表达式可以访问lambda表达式块外部的变量,这称为闭包。闭包是一个很好的功能,但如果使用不当,会很危险。例如:
int someVal = 5;
Func<int,int> f = x => x+someVal;
假定以后修改了变量someVal,于是调用委托f时,会使用someVa的新值:
someVal = 7;
f(3);//结果为10而不是8.
特别是,通过另一个线程调用lambda表达式时,我们可能不知道进行了这个调用,也不知道外部变量的当前值是什么。
所以在使用闭包时,一定要谨慎!!!
在lambda表达式访问lambda表达式块外部的变量时,编译器在定义lambda表达式时,编译器会创建一个匿名类,它用一个构造函数来传递外部变量。该构造函数取决于从外部传递进来的变量个数和类型。
对于lambda表达式Func<int,int> f = x => x+someVal;
public class AnonymousClass
{
private int someVal;
public AnonymousClass(int someVal)
{
this.someVal = someVal;
}
public int AnonymousMethod(int x)
{
retrun x+someVal;
}
}
使用lambda表达式并调用该方法的时,会创建匿名类的一个实例,并传递调用该方法时变量的值。
4.使用foreach语句的闭包
先看下面这个例子:
var values = new List<int>() {10,20,30};
var funcs = new List<Func<int>>();
foreach(var val in values)
{
funcs.Add(() => val);
}
foreach(var f in funcs)
{
Console.WriteLine((f()));
}
第一条foreach语句添加了funcs列表中每个元素。添加到列表中的函数使用lambda表达式。该lambda表达式使用了一个变量val,该变量在lambda表达式的外部定义为foreach语句的循环变量。第二条foreach语句迭代funcs列表,以调用列表中引用的每个函数。
在C#5.0之前版本编译这段代码时,会在控制台输出30三次。这是因为,在第一个foreach循环中使用闭包,所创建的函数是在调用时,而不是在迭代时获得val变量的值。在https://www.jb51.net/article/244045.htm中介绍foreach时讲到编译器会从foreach语句中创建一个while循环。在C#5.0之前版本中,编译器在while循环外部定义循环变量,在每次迭代中重用这个变量。因此,在循环结束时,该变量的值就是最后一次迭代时的值。要想在使用C#5.0之前版本时,输出10,20,30,需要将代码改为使用一个局部变量:
var values = new List<int>() {10,20,30};
var funcs = new List<Func<int>>();
foreach(var val in values)
{
var v = val;
funcs.Add(() => v);
}
foreach(var f in funcs)
{
Console.WriteLine((f()));
}
在C#5.0中,不再需要做这种代码修改。C#5.0会在while循环的代码中创建一个不同的局部循环变量。
来源:https://www.cnblogs.com/afei-24/p/6795233.html
猜你喜欢
- 前言taptap-developer是一个spring boot框架驱动的纯Grpc服务,所以,只用了四步,移除了web和spring cl
- 1.概述做一个项目,突然需要实现回复功能,所依记录一下此次的一个实现思路,也希望给别人分享一下,估计代码还是不够完善,有空在实现分页功能。话
- Collections工具类Java里关于聚合的工具类,包含有各种有关集合操作的静态多态方法,不能实例化(把构造函数私有化)public c
- 在Java中如果一个类同时继承接口A与B,并且这两个接口中具有同名方法,会怎么样?动手做实验:interface A{ void
- 环境配置Jdk1.8 + Tomcat8.5 + mysql + Eclispe(IntelliJ IDEA,Eclispe,MyEclis
- 本文实例为大家分享了C#强制转换和尝试转换的方法,供大家参考,具体内容如下将String[]类型的Object类型,转换为String[]类
- 本次数据请求使用postman, postman下载地址:https://www.getpostman.com/一、页面跳转1. 页面跳转@
- @JsonFormat处理LocalDateTime失效Failed to convert property value of type &
- 本文实例讲述了Java创建和启动线程的两种方式。分享给大家供大家参考,具体如下:方式1:继承Thread类步骤:1):定义一个类A继承于ja
- 这篇文章主要介绍了Java实现inputstream流的复制代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习
- 单例模式算是设计模式中最容易理解,也是最容易手写代码的模式,但是其中涉及的知识点却一点也不少,所以经常作为面试题来考。一般单例都是五种写法:
- 本文实例讲述了Java date format时间格式化操作。分享给大家供大家参考,具体如下:import java.util.Date;i
- 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是
- 对象类型转换分为向上转型和向下转型(强制对象转型)。 向上转型是子对象向父对象转型的过程,例如猫类转换为动物类;向下转型是强制转型实现的,是
- 打印Java程序的线程栈信息jstack可以得知当前线程的运行情况安装jstack等命令集,jstack是开发版本jdk的一部分,不是开发版
- 本文实例讲述了Java基于递归和循环两种方式实现未知维度集合的笛卡尔积。分享给大家供大家参考,具体如下:什么是笛卡尔积?在数学中,两个集合X
- 这篇文章说明了如何通过Maven配置Spring依赖项。最新的Spring版本可以在Maven Central上找到。Maven中的Spri
- IntelliJ IDEA中实现跟eclipse一样的outline方法,查看文件内所有已经声明的方法。mac的可以在key map 里搜索
- @Valid:@Valid注解用于校验,所属包为:javax.validation.Valid。① 首先需要在实体类的相应字段上添加用于充当
- > 此文主要通过WinForm来制作一个休息提醒闹钟,通过设置时间间隔进行提醒,避免沉浸式的投入到工作或者学习当中,战斗的同时也要照顾