匿名方法与Lambda表达式

知识集锦

一、lambda表达式介绍

无参数
() =>{return "1";};
等同于
string getnum(){ return "1"; }
有两个参数
(p1, p2) =>{ return p1*p2;};
等同于
int mul(p1, p2) { return p1*p2;};

  lambda表达式可以捕获外部变量,并在其主体中使用它们。这些变量被称为捕获变量,它们会在lambda表达式创建时被复制,并在lambda表达式执行时被更新。例如:

  int factor = 2;Func<int, int> multiplier = n => n * factor;  //==》 当结构体只有一句的时候可以省略 return ,多条语句不可省略Console.WriteLine(multiplier(3)); //输出6factor = 3;Console.WriteLine(multiplier(3)); //输出9

二、lambda演进过程

//声明委托类型
public delegate void SayHandler(string name, int age);
//原始形态
SayHandler handler1=new SayHandler(  delegate(string name, int age){ Console.WriteLine("你好"); }
);
//进化1  直接去掉:new SayHandler( )
SayHandler handler2=delegate(string name, int age)
{ Console.WriteLine("你好"); 
}
//进化2 delegate去掉后,换上了一个符号“=>”,读作:goes to
SayHandler handler3=(string name, int age)=>{ Console.WriteLine("你好"); }
//进化3 因为与委托类型是一一对应关系,所以直接去掉参数类型名称
SayHandler handler4=(name, age)=>{ Console.WriteLine("你好"); }
//进化4 匿名方法只有一行代码,则花括号{} 可省略
//注:若参数列表中只有一个参数,则圆括号() 也可省略
SayHandler handler5=(name, age)=> Console.WriteLine("你好"); 

  三、lambda表达式的5中高频使用方法

  第一种  使用lambda表达式作为委托或事件处理程序

  1.1 委托是一种引用类型,它可以封装一个具有特定参数和返回值类型的方法。委托可以用来实现回调函数、事件处理程序、匿名方法等功能。lambda表达式可以直接表示为委托的代码,而不需要单独定义一个方法或一个委托类型。这样可以简化委托的创建和使用,提高代码的可读性和灵活性。

//定义一个委托类型
delegate int  CalculateHandler(int x, int y);//创建一个lambda表达式,并赋值给一个委托变量
CalculateHandler sumHandler = (x, y) => x + y;//调用委托变量,执行lambda表达式的主体
Console.WriteLine(sumHandler(1, 2)); //输出3//使用系统预定义的泛型委托类型
Func<int, int, int> multiplyHandler = (x, y) => x * y;//调用委托变量,执行lambda表达式的主体
Console.WriteLine(multiplyHandler(2, 3)); //输出6//直接将lambda表达式作为参数传递给其他方法
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };
numbers.ForEach(n => Console.WriteLine(n * n)); //输出1 4 9 16 25

  1.2 事件是一种特殊的委托,它可以在某个对象发生特定行为时通知其他对象。事件处理程序是一种特殊的方法,它可以在事件被触发时执行一些操作。lambda表达式可以直接表示为事件处理程序的代码,而不需要单独定义一个方法。这样可以简化事件处理程序的创建和使用,提高代码的可读性和灵活性

//定义一个按钮类
class Button
{//定义一个点击事件public event EventHandler Click;//定义一个触发点击事件的方法public void OnClick(){//如果有订阅了该事件的处理程序,则调用它们Click?.Invoke(this, EventArgs.Empty);}
}//创建一个按钮对象
Button button = new Button();//创建一个lambda表达式,并添加到点击事件的订阅列表中
button.Click += (sender, e) =>
{Console.WriteLine("Button clicked");
};//触发点击事件,执行lambda表达式的主体
button.OnClick(); //输出Button clicked

   第二种:使用lambda表达式作为LINQ查询的谓词或选择器

LINQ是一种语言集成查询,它可以用来对各种数据源进行查询、筛选、排序、分组等操作。LINQ查询可以使用查询表达式或方法语法来编写,其中方法语法可以使用lambda表达式来指定查询的条件或投影。lambda表达式可以直接表示为谓词或选择器的代码,而不需要单独定义一个方法。这样可以简化LINQ查询的创建和使用,提高代码的可读性和灵活性。

//定义一个数据源
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };//创建一个lambda表达式,并作为参数传递给Where方法,筛选出偶数var evenNumbers = numbers.Where(n => n % 2 == 0);//遍历LINQ查询结果,执行lambda表达式的主体
foreach (var n in evenNumbers)
{Console.WriteLine(n); //输出2 4
}//创建一个lambda表达式,并作为参数传递给Select方法,将每个数乘以10
var multipliedNumbers = numbers.Select(n => n * 10);//遍历LINQ查询结果,执行lambda表达式的主体
foreach (var n in multipliedNumbers)
{Console.WriteLine(n); //输出10 20 30 40 50
}//创建一个lambda表达式,并作为参数传递给OrderBy方法,按照数值大小排序
var sortedNumbers = numbers.OrderBy(n => n);//遍历LINQ查询结果,执行lambda表达式的主体foreach (var n in sortedNumbers)
{Console.WriteLine(n); //输出1 2 3 4 5
}

 第三种:使用lambda表达式作为Task.Run或Task.Factory.StartNew的参数

Task是一种表示异步操作的对象,它可以用来实现并行编程、异步编程、多线程编程等功能。Task可以使用Task.Run或Task.Factory.StartNew方法来创建和启动,这些方法可以接受一个委托作为参数,表示要在任务中执行的代码。lambda表达式可以直接表示为委托的代码,而不需要单独定义一个方法。这样可以简化Task的创建和使用,提高代码的可读性和灵活性。

//创建一个lambda表达式,并作为参数传递给Task.Run方法,创建并启动一个任务
var task = Task.Run(() =>
{    //在任务中执行一些耗时的操作Thread.Sleep(1000);//返回一个结果return 42;
});//等待任务完成,获取任务的结果
int result = task.Result;
Console.WriteLine(result); //输出42//创建一个lambda表达式,并作为参数传递给Task.Factory.StartNew方法,创建并启动一个任务
var task2 = Task.Factory.StartNew(() =>
{//在任务中执行一些耗时的操作Thread.Sleep(1000);//抛出一个异常throw new Exception("Something went wrong");
});//等待任务完成,获取任务的异常
try
{task2.Wait();
}
catch (AggregateException ae)
{foreach (var e in ae.InnerExceptions){Console.WriteLine(e.Message); //输出Something went wrong}
}

第四种 使用lambda表达式作为表达式树

表达式树是一种表示代码结构的数据结构,它可以用来实现动态编译、元编程、LINQ提供程序等功能。表达式树可以使用Expression<TDelegate>类型来创建和表示,这是一种特殊的委托类型,它可以接受一个lambda表达式作为参数,表示要在表达式树中表示的代码。lambda表达式可以直接表示为表达式树的代码,而不需要单独定义一个方法。这样可以简化表达式树的创建和使用,提高代码的可读性和灵活性。

//创建一个lambda表达式,并作为参数传递给Expression<Func<int, int, int>>类型的构造函数,创建一个表达式树对象
Expression<Func<int, int, int>> expression = (x, y) => x + y;//遍历表达式树对象,获取表达式树的结构
Console.WriteLine(expression); //输出(x, y) => (x + y)
Console.WriteLine(expression.Body); //输出(x + y)
Console.WriteLine(expression.Parameters[0]); //输出x
Console.WriteLine(expression.Parameters[1]); //输出y//转换表达式树对象,编译为委托
Func<int, int, int> func = expression.Compile();//调用委托,执行lambda表达式的主体
Console.WriteLine(func(1, 2)); //输出3

第五种 使用lambda表达式作为异步方法

异步方法是一种使用async和await关键字来实现异步编程的方法,它可以用来实现非阻塞的UI、并发的网络请求、异步的IO操作等功能。异步方法可以使用Task或Task<T>类型来表示异步操作的结果,它们可以接受一个lambda表达式作为参数,表示要在异步方法中执行的代码。lambda表达式可以直接表示为异步方法的代码,而不需要单独定义一个方法。这样可以简化异步方法的创建和使用,提高代码的可读性和灵活性。

关键字来标记异步处理的代码,并使用await关键字来等待异步操作的完成。
- 将lambda表达式作为参数传递给Task或Task<T>类型的方法,如Task.Run或Task.FromResult,创建并启动一个异步方法。
- 等待异步方法完成,获取异步方法的结果或异常。例如,下面的代码演示了如何使用lambda表达式作为异步方法:
//创建一个lambda表达式,并作为参数传递给Task.Run方法,创建并启动一个异步方法
var task = Task.Run(async () =>
{//在lambda表达式中使用async和await关键字来标记异步处理的代码await Task.Delay(1000); //等待1秒return42; //返回一个结果
});//等待异步方法完成,获取异步方法的结果
int result = await task;
Console.WriteLine(result); //输出42//创建一个lambda表达式,并作为参数传递给Task.FromResult方法,创建并启动一个异步方法
var task2 = Task.FromResult(async () =>
{//在lambda表达式中使用async和await关键字来标记异步处理的代码await Task.Delay(1000); //等待1秒thrownew Exception("Something went wrong"); //抛出一个异常
});//等待异步方法完成,获取异步方法的异常try
{await task2;
}
catch (Exception e)
{Console.WriteLine(e.Message); //输出Something went wrong
}

二、匿名方法
简介在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法。而 C# 2.0 -- 引进了匿名方法,在 ≥ C# 3.0 的版本中,我们会用 Lambda 表达式进行取代匿名方法,并且用 Lambda 表达式作为编写内联代码的首选方式,因为它更简洁。匿名方法是,顾名思义,匿名方法就是没有名称的方法。匿名方法最明显的好处就是:可以降低额外另写一个方法的工作量;另外一个好处就是可以直接访问调用者的变量,从而降低传参的复杂度。匿名方法,它不是一个事先定义的方法,而是使用一个委托的代码块,在使用时,和普通方法并没有什么区别,但是匿名方法可以在一定程度上减少系统开销。匿名方法,关键字:delegate。匿名方法,使用场景:通常在,①需要一个临时的方法,并且该方法使用的次数极少;②该方法的代码很短,不长。匿名方法的参数使用范围:匿名方法块。如果目标在块外部,你在匿名块内部使用 -- 跳转的关键字(类似 goto/break/continue),就是错误的;如果目标在块内部,你在匿名块外部使用 -- 跳转的关键字(类似 goto/break/continue),也是错误的。如果局部变量和参数的范围已经包含匿名方法声明,则该局部变量和参数将被称为该匿名方法的“外部”(外界)变量。你看,这个代码段中的 num 就是一个外部(外界)变量:int num = 250;MyDel del = delegate() { WriteLine("#:{0}", --num); };这个外部变量的所引用的 num,将会被认为是在创建委托时进行捕获的,它与我们常用的本地变量不同,这个外部变量的生存期 -- 引用该匿名方法的委托对象被 .NET 的 CLR 的垃圾回收机制进行回收。【注意】匿名方法无法访问外部(外界)范围内,带 ref 与 out 关键字的参数。【注意】在匿名块中不能访问 unsafe 的代码。【注意】在 is 运算符的左边,是用不了匿名的方法的。

三、匿名方法与Lambda表达式的区别

  Lambda表达式和匿名方法的比较
  第一、Lambda表达式本身就是匿名方法。
  第二、Lambda表达式允许不指明参数类型,但是匿名方法必须要明确。
  第三、Lambda表达式允许单一的表达式或多条语句组成,而匿名方法不允许单一表达式。

CalculatorDelegate cal2 = delegate (int a,int b)
{return a-b;
}public delegate int CalculatorDelegate(int a,int b);
CalculatorDelegate cal3 = (int a, int b) => { return a + b; }; 
CalculatorDelegate cal4 =(a,b)=>a-b;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/39667.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么在电脑上录屏?跟着教程一步步操作

随着数字化时代的到来&#xff0c;电脑录屏已经成为一项必备技能。无论是录制游戏画面、制作教程视频&#xff0c;还是保存线上会议记录&#xff0c;录屏都能帮上大忙。可是怎么在电脑上录屏呢&#xff1f;本文将介绍两种在电脑上进行录屏的方法&#xff0c;这两种方法各有特点…

陶建辉当选 GDOS 全球数据库及开源峰会荣誉顾问

近日&#xff0c;第二十三届 GOPS 全球运维大会暨 XOps 技术创新峰会在北京正式召开。本次会议重点议题方向包括开源数据库落地思考、金融数据库自主可控、云原生时代下数据库、数据库智能运维、数据库安全与隐私、开源数据库与治理。大会深入探讨这些方向&#xff0c;促进了数…

宇宙第一大厂亚马逊云科技AWS人工智能/机器学习证书即将上线,一篇文章教你轻松拿下

据麦肯锡《在华企业如何填补AI人才缺口》研究表明&#xff0c;到2030年人工智能为中国带来的潜在价值有望超过1万亿美元&#xff0c;而随着各大企业进入人工智能化&#xff0c;对该领域的人才需求将从目前的100万增长到2030年的600万。然而到保守估计&#xff0c;到2030可以满足…

DevOps:开发与运维的无缝融合

目录 前言1. DevOps的起源与概念1.1 DevOps的起源1.2 DevOps的定义 2. DevOps的核心实践2.1 持续集成2.2 持续交付2.3 自动化 3. DevOps工具链3.1 版本控制系统3.2 持续集成工具3.3 配置管理工具3.4 容器化与编排工具3.5 监控和日志工具 4. DevOps的实际应用4.1 案例分析&#…

C语言实战 | 用户管理系统

近期推出的青少年防沉迷系统&#xff0c;采用统一运行模式和功能标准。在“青少年模式”下&#xff0c;未成年人的上网时段、时长、功能和浏览内容等方面都有明确的规范。防沉迷系统为青少年打开可控的网络空间。 01、综合案例 防沉迷系统的基础是需要一个用户管理系统管理用户…

C# 计算椭圆上任意一点坐标

已知圆心坐标 &#xff08;x0&#xff0c;y0&#xff09;&#xff0c;横轴 A&#xff08;长半轴&#xff09;&#xff0c;竖轴 B&#xff08;短半轴&#xff09;&#xff0c;角度 a&#xff0c;则圆边上点&#xff08;x&#xff0c;y&#xff09;的坐标为&#xff1a; 方法一 …

docker push 推送镜像到阿里云仓库

1.登陆阿里云 镜像服务&#xff0c;跟着指引操作就行 创建个人实例&#xff0c;创建命名空间、镜像仓库&#xff0c;绑定代码源头 2.将镜像推送到Registry $ docker login --username*** registry.cn-beijing.aliyuncs.com $ docker tag [ImageId] registry.cn-beijing.aliy…

Vue入门-如何创建一个Vue实例

创建一个一个Vue实例总共分为四步&#xff1a; 1.创建一个容器 2.引包&#xff1a;地址栏搜索v2.cn.vuejs.org这是vue2的官网地址&#xff0c;把2去掉就是vue3的官网地址&#xff0c;我们的包分为开发版本和生产版本&#xff0c;开发版本包含完整的警告和调试模式生产版本删除…

太阳辐射系统日光全光谱模拟太阳光模拟器

太阳光模拟器是一种用于评估太阳能电池性能的重要设备。它能够模拟太阳光的特性&#xff0c;通过测试电池的短路电流、开路电压、填充因子和光电转化效率等关键指标&#xff0c;来评估电池的性能优劣。 设备型号&#xff1a;KYF-GC004品牌制造商&#xff1a;科迎法电气太阳光模…

UE5基本操作(二)

文章目录 前言相机的移动速度修改默认地图使用初学者内容包文件夹结构 总结 前言 在我们的上一篇文章中&#xff0c;我们已经介绍了一些Unreal Engine 5&#xff08;UE5&#xff09;的基本操作。UE5是一款强大的游戏开发引擎&#xff0c;它提供了许多工具和功能&#xff0c;使…

蓝牙压力测试和稳定性测试工具(nRF Connect)

蓝牙压力测试和稳定性测试工具&#xff08;nRF Connect&#xff09; 文章目录 1、如何使用nRF Connect事件记录功能2、如何使用nRF Connect录制操作2.1、点击右下角的开始录制2.2、输入想要测试的指令2.3、模拟持续数据访问2.4、开始压力测试 1、如何使用nRF Connect事件记录功…

【python】OpenCV—QR Code

文章目录 1 QR Code2 准备工作3 生成 QR 码4 读取 QR 码5 与 Zbar 比较 1 QR Code QR Code&#xff08;Quick Response Code&#xff09;是一种二维条码&#xff0c;由日本Denso-Wave公司于1994年发明。QR Code的主要特点是存储信息量大、编码范围广、容错能力强、识读速度快&…

基于PI控制的三相整流器控制系统的simulink建模与仿真,包含超级电容充电和电机

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于PI控制的三相整流器控制系统的simulink建模与仿真,用MATLAB自带的PMSM电机设为发电机&#xff0c;输入为转速&#xff0c;后面接一个可以调节电流的三相整流器&#xff0c…

three.js地理坐标系有哪些,和屏幕坐标系的转换。

坐标系很好理解&#xff0c;就是点线面体的位置&#xff0c;一个点是一个坐标&#xff0c;一条线段2个坐标&#xff0c;一个矩形四个坐标&#xff0c;一个立方体8个坐标&#xff0c;three.js面对的是三维空间&#xff0c;屏幕则是二维的&#xff0c;这就面临着转换问题&#xf…

数字化精益生产系统--SRM供应商关系管理

SRM供应商关系管理&#xff0c;全称为Supplier Relationship Management&#xff08;供应商关系管理&#xff09;系统&#xff0c;是一种专门用于管理采购供应链和供应商关系的软件系统。该系统通过集成各个环节的采购活动&#xff0c;帮助企业实现采购流程的自动化、标准化和优…

hive的表操作

常用的hive命令 切换数据库use test;查询表的建表信息show create table 数据库名称.表名;查看表的类型信息desc formatted 数据库名称.表名; 删除内部表 drop table 数据库名称.表名; 先启动hdfs &#xff0c;mysql &#xff0c; hiveservice2&#xff0c;beeline CREATE [EX…

持续部署的7个陷阱及其避免方法

什么是持续部署&#xff1f; 持续部署是一种软件开发实践&#xff0c;其中代码更改会自动部署到生产中&#xff0c;无需开发人员或运营团队的明确批准。这实现了从开发到部署的完全自动化流程&#xff0c;确保新功能、错误修复和更新能够快速提供给最终用户。通过将此流程集成…

昇思25天学习打卡营第9天|MindSpore-Vision Transformer图像分类

Vision Transformer图像分类 Vision Transformer(ViT)简介 近些年,随着基于自注意(Self-Attention)结构的模型的发展,特别是Transformer模型的提出,极大地促进了自然语言处理模型的发展。由于Transformers的计算效率和可扩展性,它已经能够训练具有超过100B参数的空前…

某Dota/IM的某电竞对战平台玩家助手、查看战绩、胜率等

功能说明 WAR3游戏启动后&#xff0c;可以自动获取游戏双方的玩家列表&#xff0c;然后查询显示玩家的战绩及个人信息。附带查看玩家的战绩详情、最近游戏&#xff0c;查看对手及友方的战绩详情&#xff0c;据此推算出是否开黑、是否小号等信息 使用方法及运行效果 启动 查…

【C++题解】1456. 淘淘捡西瓜

问题&#xff1a;1456. 淘淘捡西瓜 类型&#xff1a;贪心 题目描述&#xff1a; 地上有一排西瓜&#xff0c;每个西瓜都有自己的重量。淘淘有一个包&#xff0c;包的容量是固定的&#xff0c;淘淘希望尽可能在包里装更多的西瓜&#xff08;当然要装整个的&#xff0c;不能切开…