一、局部方法(方法定义在 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. 完整执行流程(必懂)
-
调用
MyArray.Find,传入数组和Lambda匿名条件函数; -
方法内部先校验数组、条件函数是否为空,防止报错;
-
循环遍历数组每一个元素,将元素传入Lambda函数(v = 当前遍历元素);
-
Lambda函数执行条件判断,返回true/false;
-
返回true:匹配成功,立即返回当前元素,结束方法;
-
全部遍历完成无匹配,返回默认值0。
5. 拓展对应异常知识点
cs
// 1. 索引越界异常:访问数组不存在的下标
// Console.WriteLine(ages[10]); // System.IndexOutOfRangeException
// 2. 除零异常:除数不能为0
// int a = 10;
// Console.WriteLine(a / 0); // System.DivideByZeroException
八、全文终极背诵总结
-
局部方法:定义在方法内部,就近调用优先级最高
-
Lambda:匿名箭头函数,专门简化高阶函数回调
-
Func:有返回值,最后一个泛型是返回值类型
-
Action:无返回值,只执行逻辑
-
Predicate:单参数、返回bool,专属数组条件查询
-
Lambda简写规则:单参省括号、单行省return和大括号
-
Where筛选结果必须 ToArray() 才能转为数组使用