c#Lambda 表达式与事件核心知识点整理
一、Lambda 表达式
1. 概念 Lambda 表达式是一种匿名函数(无名称的函数),简化了委托和匿名方法的写法,格式为: (参数列表) => 表达式或语句块
它可以作为参数传递,或赋值给委托类型变量。
2. 基本语法与简写规则
形式 | 说明 | 示例 |
---|---|---|
完整形式 | 带参数类型、大括号和 return | (int a, int b) => { return a + b; } |
省略参数类型 | 编译器自动推断参数类型 | (a, b) => { return a + b; } |
单参数省略括号 | 只有一个参数时,可省略() | a => { return a * 2; } |
单表达式省略大括号 | 函数体只有一句表达式时,省略{} 和return | a => a * 2 (自动返回结果) |
3. 应用场景
作为委托参数传递(如集合查询、事件处理)
简化匿名方法的编写
配合
Func
/Action
等内置委托使用
示例:集合查询
int[] numbers = { 19, 20, 3, 18, 30 }; // 查找第一个偶数(使用Lambda作为查询条件) int firstEven = Array.Find(numbers, v => v % 2 == 0);
4. 与托的关联 Lambda 表达式需赋值给委托类型变量(如Func
/Action
)才能调用:
// Func<参数类型, 返回值类型>:带返回值的委托 Func<int, int, int> add = (a, b) => a + b; int result = add(2, 3); // 结果:5 // Action<参数类型>:无返回值的委托 Action<string> print = msg => Console.WriteLine(msg); print("Hello Lambda"); // 输出:Hello Lambda
二、事件(Event)
1. 概念 事件是一种特殊的多播委托,用于实现发布 - 订阅模式,允许对象在特定行为发生时通知其他对象。
发布者:定义事件并触发它的类
订阅者:注册事件并提供处理方法的类
2. 核心特性
基于委托实现,通常使用
EventHandler
或EventHandler<TEventArgs>
只能在声明它的类内部触发(调用
Invoke
)外部只能通过
+=
(订阅)和-=
(取消订阅)操作本质是 “安全的委托”,防止外部随意修改或触发
3. 基本用法
步骤 | 代码示例 |
---|---|
定义事件 | public event EventHandler MyEvent; |
订阅事件 | MyEvent += EventHandlerMethod; (可绑定命名方法、匿名委托或 Lambda) |
触发事件 | MyEvent?.Invoke(sender, e); (需先检查是否有订阅者) |
4. 事件处理程序的签名 必须与事件委托的签名匹配(以EventHandler
为例):
// 方法参数:事件源(sender)和事件数据(e) void EventHandlerMethod(object sender, EventArgs e) {// 处理逻辑 }
5. 多播特性 一个事件可以绑定多个处理方法,触发时按绑定顺序依次执行:
// 绑定多个处理方法 MyEvent += Method1; MyEvent += Method2; MyEvent += (s, e) => Console.WriteLine("Lambda处理"); // 触发时依次执行Method1 → Method2 → Lambda表达式 MyEvent?.Invoke(this, EventArgs.Empty);
三、Lambda 与事件的结合使用
Lambda 表达式可简化事件处理程序的绑定:
// 定义事件 public event EventHandler ButtonClick; // 使用Lambda绑定事件处理 ButtonClick += (sender, e) => {Console.WriteLine("按钮被点击了"); }; // 触发事件 ButtonClick?.Invoke(this, EventArgs.Empty);
总结
Lambda 表达式:简化匿名函数的编写,常用于简化委托参数,配合
Func
/Action
使用。事件:基于委托的发布 - 订阅机制,提供安全的跨对象通信,外部只能订阅 / 取消订阅,内部触发。
两者结合:使用 Lambda 可快速编写事件处理逻辑,减少代码冗余。
以下是 C# 中 Lambda 表达式的常见用法和示例表格,涵盖基本语法、场景及说明:
类型 | 语法格式 | 示例代码 | 说明 |
---|---|---|---|
无参数 | () => 表达式 | () => Console.WriteLine("Hello") | 无输入参数,执行单一表达式或语句块 |
单参数 | 参数 => 表达式 | x => x * 2 | 单个参数可省略括号,表达式返回计算结果 |
多参数 | (参数1, 参数2) => 表达式 | (a, b) => a + b | 多个参数需用括号包裹,用逗号分隔 |
语句块 | 参数 => { 语句; } | n => { if (n > 0) return "正"; else return "负"; } | 复杂逻辑需用{} 包裹,需显式使用return 返回值 |
委托匹配 | 与委托签名一致 | Func<int, bool> isEven = x => x % 2 == 0; | 匹配Func<int, bool> 委托(输入 int,返回 bool) |
事件处理 | 简化事件订阅 | button.Click += (s, e) => Console.WriteLine("Clicked"); | 替代传统的事件处理方法,简化代码 |
LINQ 筛选 | 结合Where 方法 | var adults = people.Where(p => p.Age >= 18); | 在 LINQ 中用于定义筛选条件,p 代表集合中的每个元素 |
LINQ 投影 | 结合Select 方法 | var names = people.Select(p => p.Name); | 提取元素的特定属性,转换为新的序列 |
排序条件 | 结合OrderBy 方法 | var sorted = numbers.OrderBy(n => n); | 定义排序依据,此处按元素本身升序排序 |
匿名类型创建 | 生成匿名对象 | people.Select(p => new { p.Name, AgeGroup = p.Age / 10 * 10 }) | 在 LINQ 中创建匿名类型,包含指定字段(如Name 和AgeGroup ) |
闭包捕获变量 | 访问外部变量 | int threshold = 10; var filtered = list.Where(x => x > threshold); | 可访问 Lambda 表达式外部的变量(threshold ),形成闭包 |
异步 Lambda | 结合async/await | async () => await HttpClient.GetAsync("https://example.com") | 用async 修饰,内部可使用await ,返回Task 或Task<T> |
关键特性说明:
简洁性:相比匿名方法,语法更简洁,省略了
delegate
关键字和参数类型(编译器自动推断)。类型推断:参数类型通常可省略,编译器会根据上下文(如委托类型、LINQ 方法)自动推断。
不可变性:Lambda 表达式本身是匿名函数,无法直接调用,需赋值给委托类型(如
Func
、Action
)或作为方法参数传递。闭包特性:能捕获并访问外部作用域的变量,变量的生命周期会被延长至 Lambda 表达式使用完毕。
适用场景:主要用于简化委托调用、事件处理、LINQ 查询、异步操作等场景,减少代码冗余。