如何写出符合要求的Lambda表达式

日之朝矣

本流程面向 刚知道Lambda的语法,被别人教一个需要回调函数的方法的Lambda函数,就只会这一个方法的写法,换一个需要回调函数的方法就没法写下去的新手。

本教程使用C#编程语言,使用Visual Studio作为代码编辑器。其他语言可以参考个思路。

如果你发现了本文中任何问题,烦请您在评论区留下自己的意见,我会及时修改。

跟着下面的流程走,你可以在 不了解这个需要回调函数的方法不了解委托与泛型的概念的情况下,写出一个符合要求的 Lambda 表达式。

我们通过学习 Lambda 表达式后知道,Lambda 表达式由这几部分构成 :参数,方法体,以及返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(parameters) => { statement }

// 不同的参数的个数,语句的行数都有对应的简便写法
// 参数有多个时,需要用括号括起来
(x, y) => x + y

// 参数只有一个时,不需要括号就行
x => x*x

// 没有参数时,写个括号
() => Console.WriteLine("Ciallo~(∠·ω< )⌒★")

// 只有一行语句时,不需要代码块,不需要写 return 便会自动返回
x => x*x

// 有多行语句时,需要代码块括起来,如果需要返回值,需要显式使用 return
(x, y) =>
{
int sum = x + y;
return sum;
}

Lambda的参数从何而来?

实际上使用 Lambda 表达式 作为回调函数时,其参数往往来自于委托,可以将鼠标放在需要回调函数的方法上,上面会提示参数列表,点击对应回调函数位置的参数类型,会跳转至对应的委托定义上,那边往往会给出参数的数量与类型以及返回值的类型。不了解委托没关系,只要你学过方法的定义,你就能找到返回值和参数列表的。

什么?参数类型是个T?这我看鸡毛啊?

不要退缩,你只需要在跟着下面的流程走就可以了,从此处开始,你需要带着脑子,并开始上手跟着操作!

T 一般表示泛型,泛型泛型,也就是泛用的类型,和你的传入的其他参数的类型有关。

只看文字可能有些抽象,举个例子:

1
2
3
// 要求使用Array.Find(),找出a数组中能被8整除的数
int[] a = {2,4,124,23,4,32,1,42};
Array.Find();

此时不确定 Array.Find() 里面要输入什么参数,就把鼠标放在 Find 上,会出现一个框框,最上面第一行显示了这些信息:

1
T? Array.Find<T>(T[] array, Predicate<T> match)

可以看到,出现了四次T,这些T代表的都是同一类型,也就是说,一旦确定了其中一个T的准确类型,其他T也要保持一致

第一个 T? :它所处位置正好是方法返回值的位置,代表的是Array.Find<T>()这个方法的返回值类型,是 可空的任意类型。

第二个<T>:声明 Array.Find<T>() 方法是一个泛型方法,并且 T 是该方法的类型参数,可以是任何类型。

第三个T[]:表示类型 T 的数组,其中 T 是调用 Array.Find<T>() 时确定的类型。

第四个<T>:这正好是我们所需要的回调函数的类型,Predicate<T> 是一个委托类型,接受一个 T 类型的参数并返回一个 bool

鼠标点击 Predicate<T>,我们可以查看到这个委托的定义

1
public delegate bool Predicate<in T>(T obj)

参数类型还是T!但是能确定的是,只有一个参数,并且返回值类型是 bool

回到我们的例子中,将int数组a放进Array.Find()中,然后根据已知信息(只有一个参数,并且返回值类型是 bool)便能写出一个完整的 Lambda 表达式了。

1
2
3
int[] a = {2,4,124,23,4,32,1,42};
// 现在已知只有一个参数,以及返回值是 bool 类型, 先随便写个参数名 item 放上去,方法体先随便写个布尔表达式。
Array.Find(a, item => item == 4 );

这时,把鼠标再次放到Find上,会发现最上面那行的提示信息变了!

1
2
3
4
int Array.Find<int>(int[] array,Predicate<int> match)

// 注释掉的是原来的,方便比较
// T? Array.Find<T>(T[] array, Predicate<T> match)

所有的T都变成了int,这就说明,T和参数a数组有关

a 数组是 int[]类型,对应的参数正是T[],因此,所有的T都变成了int

Predicate<T>T也变成了int,也就是说,Predicate的参数也从 (T obj)变成了(int obj)

至此,我们确定了 Lambda 的 返回值为 bool 类型,只有一个参数,且参数为 int类型。

而最后我们要确定的就是,我们 Lambda 的这个int类型的参数item代表着什么,Lambda 表达式的方法体要怎么写。

我们再次把鼠标放在Find()上,在最上面那行提示中,点击Find,查看Array.Find()的源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Predicate<T> match 就是我们的 Lambda 表达式
public static T? Find<T>(T[] array, Predicate<T> match)
{
if (array == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}

if (match == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}

for (int i = 0; i < array.Length; i++)
{
// 在这里调用了回调函数,也就是我们的 Lambda 表达式,传入的参数是数组a的一个元素
if (match(array[i]))
{
return array[i];
}
}
return default;
}

不难看出,这个for循环,是在遍历我们a数组的所有元素

match(array[i])在这里将此次循环对应的a数组的元素作为参数,去调用我们的Lambda表达式,

从这里我们得出了目前缺失的构建 Lambda表达式 的两条信息之一,item这个参数所代表的含义。item也就是a数组的一个元素。

match(array[i])在每次循环中,将a数组的一个元素作为参数,执行后返回一个布尔值,也就是 a数组的这个元素,进入我们所写的 Lambda 表达式中,经过我们写的逻辑后,返回一个布尔值,表示是否满足了某种条件。如果满足该条件,Array.Find()便返回这个元素。

回想我们调用Array.Find()这个方法的初衷,是为了从a数组中寻找满足自己所要求的条件的元素

到这里,我们便可以确定,math()应该是想让我们决定我们要寻找的元素需要符合什么样的条件,比如寻找开平方后等于16的元素,又比如寻找值为4的元素。

我们的要求是:找出a数组中能被 8 整除的元素。

至此,我们得到最后一个 目前缺失的构建 Lambda表达式 的最后一条信息:Lambda 表达式的方法体要写什么。也就是要判断传入的a数组的元素是否能被 8 整除;

现在我们便可以确定 Lambda 表达式最终的写法了!

1
2
3
int[] a = {2,4,124,23,4,32,1,42};
// 找出a数组中能被8整除的数, item % 8 == 0
Array.Find(a, item => item % 8 == 0 );

到这里我们便完成了一次从 不知道Lambda表达式要怎么写 ,到完成一个 Lambda 表达式的过程。

如果你理解能力强,或者经过上面的步骤后,仍然无法确定符合要求的Lambda表达式该怎么写,可以把鼠标放在Find()上,下面有一个GitHub 示例和文档,点进去,去参考别人在使用这个方法时,是如何书写Lambda表达式的。

留一个作业来检验你的学习成果,或者说来熟悉上述的流程:

1
2
3
// 使用 Array.Exists() 判断 s 数组中是否存在 “日之朝矣” 这个字符串
string[] sArr = {"rzzy", "RiZhiZhaoYi", "日之朝矣", "RZZY"};
Array.Exists();

答案:

点击展开 查看答案
1
2
3
4
5
6
// 使用 Array.Exist() 判断 s 数组中是否存在 “日之朝矣” 这个字符串
string[] sArr = {"rzzy", "RiZhiZhaoYi", "日之朝矣", "RZZY"};
bool exists = Array.Exists(sArr, s => s.Equals("日之朝矣"));
Console.WriteLine($"""sArr中{(exists ? "存在":"不存在")} "日之朝矣" 这个字符串""");

// output: sArr中存在 "日之朝矣" 这个字符串
  • 标题: 如何写出符合要求的Lambda表达式
  • 作者: 日之朝矣
  • 创建于 : 2024-07-27 22:28:53
  • 更新于 : 2024-08-18 09:25:27
  • 链接: https://blog.rzzy.fun/2024/07/27/write-Lambda-expressions-that-meet-the-requirements/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
此页目录
如何写出符合要求的Lambda表达式