C#Lambda表达式

一、局部方法(方法定义在 Main 内部)

1. 核心特点

  • 可以在方法内部定义方法(局部方法)

  • 就近原则:当前代码执行,优先调用离自己最近的方法,而非外部全局方法

  • 局部方法仅在当前方法内有效,外部无法调用

2. 无返回值局部方法

cs 复制代码
// Main内部定义局部方法
void F1()
{
    Console.WriteLine("我是在main里面定义的方法");
}
F1(); // 直接调用

3. 有返回值局部方法(就近优先级)

cs 复制代码
int F2(int a, int b)
{
    return a + b;
}
Console.WriteLine(F2(10, 20)); // 30

规则:如果类外部也有同名 F2 方法,代码优先调用内部局部方法

4. 局部方法优化数组高阶调用

解决传统写法弊端:不用反复在类外部写静态回调方法

cs 复制代码
int[] ages = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine(Array.Find(ages, F3)); // 2

// 内部局部回调方法
bool F3(int v)
{
    return v % 2 == 0;
}

二、Lambda 表达式(匿名函数/箭头函数)

1. 核心概念

  • Lambda 本质:匿名函数(没有方法名的函数)

  • 作用:专门作为高阶函数参数使用,简化回调写法

  • 固定语法:(参数) => { 函数体 }

2. Lambda 三种接收委托(必考)

单独 Lambda 不能直接运行,必须:要么交给高阶方法、要么用委托变量接收

  • Func<> :接收有返回值的函数

  • Action<> :接收无返回值的函数

  • Predicate<> :接收返回值固定为bool、单参数的函数(专用于数组条件查询)

3. Lambda 完整写法 + 极简简写规则

cs 复制代码
// 1. 完整版(参数带类型、带大括号、带return)
Func<int, int, int> F4 = (int a, int b) => { return a + b; };

// 2. 简写1:省略参数类型(编译器自动推断)
Func<int, int, int> F5 = (a, b) => a + b;

// 3. 简写2:单个参数,可省略小括号
Func<int, int> F6 = a => a;

简写口诀:无参必括号、单参可省略、单行省return和大括号

四、LINQ Where 筛选(拓展)

Where 筛选满足条件的元素,返回可枚举类型,需搭配ToArray() 转为数组

cs 复制代码
// 筛选所有长度为3的字符串
string[] ss = strings.Where(a => a.Length == 3).ToArray();
Console.WriteLine(string.Join("-", ss));

五、四种写法迭代升级(从繁琐到极简)

  • 1.0 最老写法:回调方法定义在 Main 外部(最繁琐)

cs 复制代码
Console.WriteLine(Array.FindIndex(ages, FindEven));//0

public static bool FindEven(int v)
{
    return v % 2 == 0;
}
  • 2.0 局部方法写法:回调方法定义在 Main 内部(就近、方便)

cs 复制代码
Console.WriteLine(Array.Find(ages, F9)); //2 
bool F9(int v)
{
    return v % 2 == 0;
}
  • 3.0 委托变量写法:Lambda赋值给 Func/Predicate 变量,可复用

cs 复制代码
Func<int, bool> F7 = v => v % 2 != 0;

//Predicate<> 接收返回值为bool类型,所以不用在定义时候 Predicate<int>写bool类型
Predicate<int> F8 = v => v % 2 != 0;
Console.WriteLine(Array.Find(ages, F8)); //无法从Func<> 转成Predicate<>
  • 4.0 终极写法:直接把 Lambda 写进高阶方法参数(企业最常用)

六、三大委托详细详解

1. Func<> 有返回值委托

规则:Func <参数1类型, 参数2类型, ..., 返回值类型>最后一个泛型永远是返回值

cs 复制代码
// 判断素数案例
Func<int, bool> F1 = a =>
{
    bool isShuSu = true;
    for (int i = 2; i < a; i++)
    {
        if (a % i == 0)
        {
            isShuSu = false;
            break;
        }
    }
    return isShuSu;
};
Console.WriteLine(F1(8)); // false

// 搭配数组All方法使用(全部满足条件)
int[] ages = { 3, 5, 7 };
Console.WriteLine(ages.All(F1)); // true

2. Action<> 无返回值委托

无返回值,只负责执行逻辑,常用于遍历操作

cs 复制代码
// 打印偶数
Action<int> F2 = a =>
{
    if (a % 2 == 0)
    {
        Console.WriteLine(a);
    }
};

// 单独调用
F2(3);

// 搭配数组ForEach遍历
int[] ages1 = { 3, 5, 7, 4 };
Array.ForEach(ages1, F2);

3. Predicate<> 布尔条件委托

固定:单个参数、返回值必须是bool,专门适配数组Find/FindAll/Exists等条件方法

cs 复制代码
Predicate<int> F3 = (a) =>
{
    return a * a > 25;
};
Console.WriteLine(F3(6)); // true

// 筛选所有平方大于25的元素
int[] ages2 = { 3, 5, 7, 4, 8 };
int[] arr = Array.FindAll(ages2, F3);
Console.WriteLine(string.Join("-", arr)); //7-8
重点报错注意

Func<int,bool>不能直接替换 Predicate<int>,二者类型不兼容,数组条件方法优先用 Predicate

七、手写底层:Lambda+Func 实现官方 Array.Find 原理(核心重点)

1. 原理概述

官方 Array.Find() 本质就是:循环遍历数组 + 调用传入的Lambda/Func条件函数 + 匹配成功立即返回元素,无匹配返回数据默认值,同时做参数空值校验,规避程序报错。

核心依赖:Func<int, bool> 接收Lambda匿名条件函数,完美适配高阶函数传参逻辑。

2. 完整手写底层代码

cs 复制代码
// 自定义数组工具类,复刻官方Find底层逻辑
public class MyArray
{
    // 第一个参数:目标数组
    // 第二个参数:Func委托,接收Lambda条件函数(int参数、bool返回值)
    public static int Find(int[] arr, Func<int, bool> match) 
    {
        // 参数安全校验:数组为空抛异常
        if (arr == null)
        {
            throw new ArgumentNullException("array");
        }
        // 参数安全校验:条件函数为空抛异常
        if (match == null)
        {
            throw new ArgumentNullException("match");
        }

        // 遍历数组所有元素
        for (int i = 0; i < arr.Length; i++) 
        {
            // 执行传入的Lambda条件函数,判断当前元素是否满足条件
            if (match(arr[i])) 
            {
                // 匹配成功,立即返回当前元素(终止遍历)
                return arr[i];
            }
        }
        // 遍历完毕无匹配元素,返回int默认值0
        return 0; 
    }
}

3. Lambda搭配手写Find方法调用案例

cs 复制代码
int[] ages = new int[] { 1, 2, 3 };

// Lambda判断:查找第一个偶数
Console.WriteLine(MyArray.Find(ages, v => v % 2 == 0)); // 输出2

// Lambda判断:查找第一个能被3整除的数
Console.WriteLine(MyArray.Find(ages, v => v % 3 == 0)); // 输出3

4. 完整执行流程(必懂)

  1. 调用 MyArray.Find,传入数组和Lambda匿名条件函数;

  2. 方法内部先校验数组、条件函数是否为空,防止报错;

  3. 循环遍历数组每一个元素,将元素传入Lambda函数(v = 当前遍历元素);

  4. Lambda函数执行条件判断,返回true/false;

  5. 返回true:匹配成功,立即返回当前元素,结束方法;

  6. 全部遍历完成无匹配,返回默认值0。

5. 拓展对应异常知识点

cs 复制代码
// 1. 索引越界异常:访问数组不存在的下标
// Console.WriteLine(ages[10]); // System.IndexOutOfRangeException

// 2. 除零异常:除数不能为0
// int a = 10;
// Console.WriteLine(a / 0); // System.DivideByZeroException

八、全文终极背诵总结

  1. 局部方法:定义在方法内部,就近调用优先级最高

  2. Lambda:匿名箭头函数,专门简化高阶函数回调

  3. Func:有返回值,最后一个泛型是返回值类型

  4. Action:无返回值,只执行逻辑

  5. Predicate:单参数、返回bool,专属数组条件查询

  6. Lambda简写规则:单参省括号、单行省return和大括号

  7. Where筛选结果必须 ToArray() 才能转为数组使用

相关推荐
wh_xia_jun13 小时前
Apifox 测试项目实操1
开发语言·lua
小侯不躺平.13 小时前
C++ Boost库【6】时间戳整体综合
开发语言·c++·算法
ytttr87313 小时前
基于MATLAB的三维六面体有限元网格模型
开发语言·matlab
likerhood13 小时前
Java ArrayList 详解:从动态数组到扩容机制与常见陷阱
java·开发语言·windows
枫叶丹413 小时前
【HarmonyOS 6.0】Live View Kit 实况支持显示夕阳和赏月背景的技术解读与实践
开发语言·华为·harmonyos
AI人工智能+电脑小能手13 小时前
【大白话说Java面试题 第80题】【Mysql篇】第10题:MySQL 在什么条件下索引失效?
java·开发语言·mysql·adb·面试
风吹夏回13 小时前
Python JWT 认证实战:从原理到 PyCharm 落地指南
开发语言·python·pycharm·jwt
jieyucx13 小时前
Go 语言 JSON 序列化/反序列化:Tag 用法完全指南
开发语言·golang·json·序列化·tag
小肝一下13 小时前
STL——list
开发语言·c++·stl·list·伊雷娜