CH06_Lambda表达式
第6章:Lambda表达式
本章目标
-
为什么要学习C#编程语言
-
了解C#相关常识
-
C#开发工具Visual Studio安装
-
掌握C#程序的开发步骤
-
掌握C#的注释
-
掌握C#的常用转义符
本章内容
lambda表达式演变史
C# 匿名函数的演变历史可以追溯到 C# 语言的不同版本,随着语言特性的不断丰富和发展,匿名函数经历了以下几个主要阶段:
C# 1.0
在 C# 1.0 中,虽然还没有直接支持匿名函数的概念,但已经引入了委托(Delegate)这一关键概念。委托允许将方法作为参数传递或存储为变量,为后续匿名函数的引入奠定了基础。在这个版本中,若要创建委托实例,必须先定义一个具有匹配签名的方法,然后使用该方法的名称来初始化委托。
public delegate int MyDelegate(int x, int y);public static int AddNumbers(int a, int b)
{return a + b;
}MyDelegate add = new MyDelegate(AddNumbers);
C# 2.0
C# 2.0 引入了匿名方法,这是对匿名函数功能的初步实现。匿名方法允许开发者在需要委托的地方直接编写一段代码块(内联),而无需事先定义一个命名方法。这种语法简化了在特定上下文中临时创建和使用简单功能的过程,特别是在事件处理和回调场景中
MyDelegate fun = delegate(int a, int b)
{return a + b;
};
C# 3.0
C# 3.0 引入了更强大的匿名函数形式——Lambda 表达式。Lambda 表达式进一步简化了匿名方法的语法,使其更加简洁且易于阅读。Lambda 表达式可以直接表示输入参数、箭头符号(=>)以及要执行的表达式或语句块。它们在LINQ(Language Integrated Query)中扮演了核心角色,极大地增强了C#的函数式编程能力。
// 单行表达式形式
MyDelegate fun1 = (int a, int b) => a + b;// 多行语句块形式
MyDelegate fun2 = (int a, int b) =>
{int result = a * b;Console.WriteLine("Processing numbers...");return result;
};
C# 4.0
随着Lambda表达式的普及和广泛使用,匿名方法在新项目中的使用逐渐减少,Lambda表达式成为编写匿名函数的首选方式。后续版本的C#(如4.0、5.0、6.0、7.0、8.0、9.0、10.0等)继续强化和扩展了Lambda表达式的能力,包括:
- 类型推断:Lambda表达式中的参数类型可以根据上下文自动推断,进一步减少了代码冗余。
- 可变数量参数:Lambda表达式支持可变数量参数,方便处理不定长度的参数列表。
- Expression-bodied members:C# 6.0引入了表达式体成员语法,使得Lambda风格的简短表达式可以用于方法、属性、构造函数等更多场景。
- Local functions(局部函数):虽然不是匿名函数,但C# 7.0引入的局部函数提供了另一种在方法内部定义私有、嵌套函数的方式,有时可以作为匿名函数的替代方案,尤其是在需要复用或避免闭包副作用的情况下。
综上所述,C# 匿名函数的演变历史始于C# 2.0的匿名方法,经由C# 3.0的Lambda表达式实现了重大飞跃,并在后续版本中持续得到增强和完善,成为现代C#编程中不可或缺的一部分。尽管匿名方法在早期版本中有其作用,但在当前实践中,Lambda表达式已成为编写匿名函数的标准方式。
lambda 表达式使用方法
定义描述
Lambda表达式实际上是一种匿名函数,在Lambda表达式中可以包含语句以及运算等操作。并且可用于创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内联表达式。使用Lambda表达式可大大减少代码量,使得代码更加的优美、简洁,更有可观性。
基本语法
(input-parameters) => { <sequence-of-statements> }
Lambda 表达式的语法由三部分组成:
-
参数列表:位于圆括号
()内,可以为空(表示无参数)、包含一个或多个参数,参数类型可以显式声明或根据上下文推断。- 显式类型:
(int x, string y) - 类型推断:
(x, y)—— 当Lambda表达式赋值给已知委托类型或在编译器可以确定类型的情境下,可以省略参数类型。
- 显式类型:
-
箭头操作符
=>:将参数列表与表达式或语句块分隔开。 -
表达式或语句块:表示Lambda表达式的行为。
-
单行表达式:直接返回表达式的计算结果,不需要使用
return关键字。 -
int[] numbers = { 1, 2, 3 }; var evenNumbers = numbers.Where(n => n % 2 == 0); -
多行语句块:使用花括号
{}包围,如果需要执行多条语句或需要显式return语句,则使用语句块形式。 -
Func<int, int> squareAndLog = number => {int squared = number * number;Console.WriteLine($"Squared: {squared}");return squared; };
-
使用场景
作为参数:Lambda 表达式常被用作需要函数作为参数的方法或操作符的参数,如 LINQ 方法、事件处理器、Action 或 Func 委托实例化等。
static void Fun1()
{List<string> stuList = new List<string> { "孙悟空", "猪八戒", "沙悟净", "唐僧" };//使用 Predicate 委托(返回类型为bool)var result1 = stuList.Find(p => p.StartsWith("孙"));// 使用 Action 委托(无返回值)Action<string> logMessage = name => Console.WriteLine($"姓名: {name}");// 使用 Func 委托(无返回值)Func<int, int, int> add = (a, b) => a + b;
}
匿名委托:Lambda 表达式可以替代传统的匿名方法,创建不需显式定义的、临时使用的委托实例。
static void Fun2()
{Button btn = new Button();// 传统匿名方法btn.Click += delegate (object sender, EventArgs e){MessageBox.Show("按钮被点击了!");};// Lambda 表达式形式btn.Click += (sender, e) => MessageBox.Show("按钮被点击了!");}
事件处理:Lambda 表达式简化了事件处理器的注册,尤其在需要访问外部变量时,可以利用闭包特性 。
static void Fun3()
{Button btn = new Button();string greeting = "hello!";btn.Click += (sender, e) => MessageBox.Show(greeting);}
注意事项
-
类型推断:Lambda 表达式的参数类型和返回类型通常可以由编译器推断,无需显式声明。但在某些情况下,可能需要显式提供类型信息以消除歧义。
-
闭包:Lambda 表达式可以捕获其封闭作用域内的变量,形成闭包。理解闭包行为对于避免潜在的并发问题和资源管理问题至关重要。
-
性能:Lambda 表达式通常编译为高效代码,但在某些情况下(如大型循环中的复杂Lambda表达式),可能会导致编译器生成额外的类和方法,影响性能。适当优化或使用局部函数替代可能有助于提升效率。
系统自带的两种委托
C# 中的 Action 和 Func 是预定义的泛型委托类型,它们简化了委托的使用,避免了手动声明相似用途的自定义委托。今后我们使用时,没有必要自定义委托了,全部使用系统自带的委托就可以了,方便省事.
Action 委托
Action 代表一个无返回值的方法,只用于封装需要执行的操作。根据需要传递的参数数量,C# 提供了一系列预定义的 Action 类型,从 Action(无参数)到 Action<typeparamref name=“T1”>, …, T16</typeparamref></typeparamref></typeparamref>(最多16个参数)。
static void Fun4()
{//无参数Action action1 = () => Console.WriteLine("无参.");action1(); //带参数Action<string, int> paramAction = (name, age) => Console.WriteLine($"{name}, count: {age}");paramAction("张三", 18); }
Func 委托
Func 代表一个有返回值的方法,除了封装操作外,还返回一个指定类型的值。Func 类型同样有一系列预定义版本,格式为 Func<typeparamref name=“T1”>, …, Tn</typeparamref>, TResult>,其中 T1 到 Tn 代表输入参数类型,TResult 代表返回值类型。
static void Fun5()
{//无参,返回整数Func<int> func1 = () => DateTime.Now.Second;int result1 = func1(); // 获取当前秒数Console.WriteLine(result1);//带参,返回字符串Func<string, int, string> fun2 = (name, age) => $"姓名:{name} ,年龄{age}";string result2 = fun2("张三", 30);Console.WriteLine(result2);Console.WriteLine("-------------------------------------------");List<string> stuList = new List<string> { "孙悟空", "猪八戒", "沙悟净", "唐僧", "孙尚香" };//查询满足要求元素的数量var count = stuList.Count(f=> f.StartsWith("孙"));//查询满足要求的元素stuList.Where(f=> f.StartsWith("孙"));Console.WriteLine("-------------------------------------------");List<Student> stuList2 =new List<Student> {new Student{Name="孙悟空",Age=500 },new Student{Name="猪八戒",Age=400 },new Student{Name="沙悟净",Age=300 },new Student{Name="唐僧",Age=800 },new Student{Name="孙尚香",Age=200 }};//最大值var max = stuList2.Max(f => f.Age);//最小值var min = stuList2.Min(f => f.Age);//平均值var avg = stuList2.Average(f => f.Age);//总和var sum = stuList2.Sum(f => f.Age);
}
Predicate 委托
Predicate泛型委托:表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素。
static void Func6()
{List<string> stuList = new List<string> { "孙悟空", "猪八戒", "沙悟净", "唐僧","孙尚香" };//所搜满足要求的第一个元素var name= stuList.Find(p=> p.StartsWith("孙"));//所搜满足要求的所有元素var names = stuList.FindAll(p=> p.StartsWith("孙"));所搜满足要求的第一个元素的索引var index= stuList.FindIndex(p => p.StartsWith("孙"));}
本章总结
总之,C# Lambda 表达式提供了简洁、直观的方式来编写匿名函数,极大地提高了代码的可读性和可维护性,尤其在处理函数式编程、事件处理、委托、LINQ 查询等方面发挥着重要作用。理解和熟练运用Lambda表达式是现代C#开发中的重要技能。
课后作业
学生类:
姓名
年龄
性别
身高
有一个学生集合,要求用lambda表达式实现以下功能:
1.查询所有姓“张”的学生。
2.查询所有姓“张”的男生
3.查询平均身高并返回
4.查询已成年的男生
5.查询身高不低于160cm的女生
6.查询女生的平均年龄,并返回。
7.查询身高不低于170cm的男生的数量
8.查询升高不低于170cm或年龄不低于18的学生
相关文章:
CH06_Lambda表达式
第6章:Lambda表达式 本章目标 为什么要学习C#编程语言 了解C#相关常识 C#开发工具Visual Studio安装 掌握C#程序的开发步骤 掌握C#的注释 掌握C#的常用转义符 本章内容 lambda表达式演变史 C# 匿名函数的演变历史可以追溯到 C# 语言的不同版本,…...
大模型本地部署实践:Ollama+Open-WebUI(MacOS)
目录 什么是Ollama Ollama安装 对话界面可视化?Open-WebUI! 安装Open-WebUI 什么是Ollama Ollama是一个为简化大语言模型本地部署与交互的开源框架。它提供了用户友好的接口,帮助开发者和模型爱好者在没有依赖外部API的基础上高效地运行、…...
JavaScript——DOM编程、JS的对象和JSON
一、DOM编程 DOM(Document Object Model)编程:就是使用document对象的API,完成对网页HTML文档进行动态修改,以实现网页数据,和样式动态变化效果的编程。 (一)DOM获取元素的多种方法 1.查找元素的函数 getElementById("id值…...
SIMCom芯讯通A7680C在线升级:FTP升级成功;http升级腾讯云对象储存的文件失败;http升级私有服务器的文件成功
从事嵌入式单片机的工作算是符合我个人兴趣爱好的,当面对一个新的芯片我即想把芯片尽快搞懂完成项目赚钱,也想着能够把自己遇到的坑和注意事项记录下来,即方便自己后面查阅也可以分享给大家,这是一种冲动,但是这个或许并不是原厂希望的,尽管这样有可能会牺牲一些时间也有哪天原…...
OSRM docker环境启动
命令一把梭 wget https://download.geofabrik.de/asia/china-latest.osm.pbf docker pull osrm/osrm-backend docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-extract -p /opt/car.lua /data/china-latest.osm.pbf docker run -t -v "${PWD}:/data&q…...
Vue3 动态获取 assets 文件夹图片
我真服了Vue3 这个老六了,一个简单图片src 赋值搞得那么复杂. //item.type 是我遍历类型的类型参数 <img alt"吐槽大会" :src"getAssetUrl(item.type)" /> 基于 Vue2 的Webpack 处理,还不错,可以用/ 这种绝对路径,可以接受,虽然多了个require很不爽…...
<项目代码>YOLOv8 草莓成熟识别<目标检测>
YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为一个回归问题,能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法(如Faster R-CNN),YOLOv8具有更高的…...
代码随想录算法训练营第五十一天|Day51 图论
岛屿数量 深搜 https://www.programmercarl.com/kamacoder/0099.%E5%B2%9B%E5%B1%BF%E7%9A%84%E6%95%B0%E9%87%8F%E6%B7%B1%E6%90%9C.html 思路 #include <stdio.h> #define MAX_SIZE 50 int grid[MAX_SIZE][MAX_SIZE]; int visited[MAX_SIZE][MAX_SIZE]; int N, M; …...
uniapp 自定义加载组件,全屏加载,局部加载 (微信小程序)
效果图 全屏加载 页面加载使用 局部加载 列表加载里面使用 使用gif html <template><view><view class"" v-if"typeFullScreen"><view class"loading" v-if"show"><view class""><i…...
STM32完全学习——系统时钟设置
一、时钟框图的解读 首先我们知道STM32在上电初始化之后使用的是内部的HSI未经过分频直接通过SW供给给系统时钟,由于内部HSI存在较大的误差,因此我们在系统完成上电初始化,之后需要将STM32的时钟切换到外部HSE作为系统时钟,那么我…...
Github 2024-11-16Rust开源项目日报 Top10
根据Github Trendings的统计,今日(2024-11-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Go项目1Python项目1Lapce:用 Rust 编写的极快且强大的代码编辑器 创建周期:2181 天开发语言:Rust协议类型:Apache License 2.0St…...
CH03_反射
第3章:反射 本章目标 掌握反射的原理 熟悉反射的基本运用 本章内容 反射是什么 C# 编译运行过程 首先我们在VS点击编译的时候,就会将C#源代码编译成程序集 程序集以可执行文件 (.exe) 或动态链接库文件 (.dll) 的形式实现 程序集中包含有Microsoft …...
vue2侧边导航栏路由
<template><div><!-- :default-active"$route.path" 和index对应其路径 --><el-menu:default-active"active"class"el-menu-vertical-demo"background-color"#545c64"text-color"#fff"active-text-col…...
core 不可变类型 线程安全 record
当一个类型的对象在创建时被指定状态后,就不会再变化的对象,我们称之为不可变类型。这种类型是线程安全的,不需要进行线程同步,非常适合并行计算的数据共享。它减少了更新对象会引起各种bug的风险,更为安全。 System.D…...
linux之调度管理(8)-SMP cpu 的 psci启动
一、psci介绍 psci是arm提供的一套电源管理接口,当前一共包含0.1、0.2和1.0三个版本。它可被用于以下场景: (1)cpu的idle管理 (2)cpu hotplug以及secondary cpu启动 (3)系统shutdo…...
review-消息中间件MQ
RabbitMQ RabbitMQ,作为当今流行的开源消息代理软件,以其卓越的可靠性、灵活性和易用性在微服务架构和分布式系统中扮演着至关重要的角色。它不仅能够确保消息在不同系统组件间的高效传递,还能通过其高级消息队列协议(AMQP&#x…...
leetcode400第N位数字
代码 class Solution {public int findNthDigit(int n) {int base 1;//位数int weight 9;//权重while(n>(long)base*weight){//300n-base*weight;base;weight*10;}//n111 base3 weight900;n--;int res (int)Math.pow(10,base-1)n/base;int index n%base;return String…...
前端网页开发学习(HTML+CSS+JS)有这一篇就够!
目录 HTML教程 ▐ 概述 ▐ 基础语法 ▐ 文本标签 ▐ 列表标签 ▐ 表格标签 ▐ 表单标签 CSS教程 ▐ 概述 ▐ 基础语法 ▐ 选择器 ▐ 修饰文本 ▐ 修饰背景 ▐ 透明度 ▐ 伪类 ▐ 盒子模型 ▐ 浮动 ▐ 定位 JavaScript教程 ▐ 概述 ▐ 基础语法 ▐ 函数 …...
CSS遮罩:mask
CSS属性 mask 允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。 // 一般用位图图片做遮罩 mask: url(~/assets/images/mask.png); mask-size: 100% 100%;// 使用 SVG 图形中的形状来做遮罩 mask: url(~/assets/images/mask.svg#star);…...
Swift闭包的本质
1 闭包的本质其实是一个引用类型:存储在堆空间上,由堆分配空间,且生命周期由ARC(自动引用计数机制)管理 2 捕获值:闭包会捕获上下文使用到的变量(引用类型会保持引用关系)ÿ…...
Gemma-3-270m镜像免配置原理:预编译GGUF、内置KV cache优化机制解析
Gemma-3-270m镜像免配置原理:预编译GGUF、内置KV cache优化机制解析 1. 开箱即用的秘密:预编译GGUF文件 你可能已经体验过,在CSDN星图镜像广场找到Gemma-3-270m的Ollama镜像,点击部署后,几乎不需要任何额外设置&…...
欧姆龙CP系列PLC数据采集实战:Fins TCP协议详解与Python代码实现
欧姆龙CP系列PLC数据采集实战:Fins TCP协议详解与Python代码实现 在工业自动化领域,PLC(可编程逻辑控制器)作为核心控制设备,其数据采集能力直接影响着生产监控与决策效率。欧姆龙CP系列PLC凭借稳定可靠的性能…...
Step3-VL-10B-Base效果实测:复杂网络拓扑图的自动分析与说明生成
Step3-VL-10B-Base效果实测:复杂网络拓扑图的自动分析与说明生成 最近在测试各种视觉语言模型,想看看它们到底能不能看懂我们工程师日常打交道的东西。正好手头有个新模型叫Step3-VL-10B-Base,听说它在理解图表方面有点东西。我琢磨着&#…...
Lychee-Rerank企业面试系统应用:Java八股文智能匹配
Lychee-Rerank企业面试系统应用:Java八股文智能匹配 最近跟几个做技术招聘的朋友聊天,发现他们有个共同的烦恼:每天要筛几十份简历,面试的时候还得现场判断候选人回答的Java八股文到底靠不靠谱。光靠面试官自己记和判断ÿ…...
揭秘Diablo Edit:探索暗黑破坏神角色定制的无限可能
揭秘Diablo Edit:探索暗黑破坏神角色定制的无限可能 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 暗黑破坏神存档编辑工具Diablo Edit为玩家提供了超越常规游戏体验的角色定制能力。…...
OnmyojiAutoScript:自动化阴阳师任务实现游戏与生活的平衡
OnmyojiAutoScript:自动化阴阳师任务实现游戏与生活的平衡 【免费下载链接】OnmyojiAutoScript Onmyoji Auto Script | 阴阳师脚本 项目地址: https://gitcode.com/gh_mirrors/on/OnmyojiAutoScript 阴阳师作为一款经典的回合制手游,丰富的游戏内…...
打工人上班摸魚小說-第十五章 地铁、跟踪与再也甩不掉的影子
# 打工人上班摸魚小說-第十五章 地铁、跟踪与再也甩不掉的影子---林舟睁开眼的时候,天已经亮了。他不知道自己是什么时候睡着的,只记得看着天花板,看着看着,眼皮就沉了。醒来的时候,阳光从窗帘的缝隙里照进来ÿ…...
Macbook Neo挤爆牙膏也没做到的,它做到了!
谁懂啊家人们!刚入手MacBook Neo就被苹果封闭生态整emo了😤想和安卓手机传文件、用Mac玩3A大作、远程操控办公电脑…结果要么各种不兼容,要么操作复杂到想摔电脑💻直到我挖到了UU远程!简直是Mac用户的救命稻草…...
程序员如何快速突击找工作?
程序员如何快速突击找工作? 针对程序员如何高效突击求职,以下分步骤详细说明: 一、精准定位与简历优化 明确目标岗位 根据技术栈(如Java后端、前端、算法等)筛选匹配岗位优先投递要求与自身技能重合度≥70%的职位 简…...
多无人机动态避障路径规划研究:基于遗传算法GA的多无人机动态避障路径规划研究(可以自定义无人机数量及起始点),MATLAB代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…...
