C# 匿名函数与Lambda表达式

本文仅作学习笔记与交流,不作任何商业用途,作者能力有限,如有不足还请斧正

1.匿名函数

在 C# 中,匿名函数是一种没有名称的函数,可以直接在代码中定义和使用

匿名函数主要有两种形式:匿名方法和Lambda 表达式

它们通常用于简化代码,特别是在需要短小函数的地方,如回调函数或内联函数

1.1匿名函数的声明与调用

首先,必须要需要清楚的一点是:匿名函数不要脱离委托和事件来使用

所以,先声明一个委托:

cs 复制代码
//一个无参无返回值的委托函数
delegate void D();

再声明一个匿名函数:

cs 复制代码
delegate () {
    Console.WriteLine("这是一个委托函数");
};

然后添加到委托中:

你可以参考这篇文章, C# 委托-CSDN博客

通过创建实例的方式去添加匿名函数,即 "new"

cs 复制代码
D d = new D(delegate () {
    Console.WriteLine("这是一个委托函数");
});

也可以直接等于一个匿名函数,即"="

cs 复制代码
D d = delegate () {
    Console.WriteLine("这是一个委托函数");
};

有点茴香豆的茴有五种写法的感觉了哈哈

1.2 匿名函数有参数

首先,你可以知道c#自定义的一些泛型委托,这样可以更好的使用匿名函数

当匿名函数有参数时,可以直接在声明的括号中定义参数

cs 复制代码
Action<int,int> action =delegate (int x, int y) {
    Console.WriteLine(x*y);
};
action(1, 5);

1.3 匿名函数有返回值

还是,你可以知道c#自定义的一些泛型委托,这样可以更好的使用匿名函数

匿名函数的返回值直接return就可以了,编译器会自动判断,委托函数考虑的就很多了

cs 复制代码
Func<int, int> func = delegate (int x) {
    return x;
};
func.Invoke(1);

再举个例子:

1.4 匿名函数的缺点

当你的委托是多播委托时,也就是一个委托添加了多个匿名函数时,当需要删除一些函数的时候就乱了套了,没有名字怎么找?没法找!

2.Lambda表达式

Lambda和匿名函数可以看作是同一个东西,只是声明上更加简洁

ps:lambda表达式不是正则表达式,因为我看到有人不知道从哪里听来的还犟

2.1 无参无返回值的Lambda表达式

cs 复制代码
Action action = () => {
    Console.WriteLine("这是一个Lambda表达式的");  
};

可以理解为把delegate 简化成了**=>** 并且放在了括号后面

2.2 有参数

cs 复制代码
Action<int> action1 = (int a) => {
    Console.WriteLine(a);
};

2.3 有返回值

cs 复制代码
Func<int, string> func = (int a) => {
    return "123";
};

2.4 闭包

闭包是指一个函数 和它的**外部环境(变量)**一起被捕获的情况

即使这个函数在定义它的作用域之外被调用,它仍然可以访问和修改这些外部变量

举个栗子:

如果我有一段代码是这么写的,返回值number是重复的 ,因为我每次调用都会释放掉中间变量count的内存

毫不意外,的结果

但是如果我想要保留count从而使得最终nmber递增,可以这么写:

cs 复制代码
Func<int, Func<int>> makeCounter = (int C) => {
    int count = C;
    return () => ++count;
};

var number = makeCounter(0);//该委托是有返回值的,所以可以用一个var变量去接收
Console.WriteLine(number()); //第一次调用
Console.WriteLine(number()); //第二次调用

得到的结果:

Q:为什么number()是一个方法?

A:因为我返回值是一个委托,而委托可以被函数装载

Q:"Var"是什么?

A:var 是 C# 中的隐式类型局部变量声明,它允许编译器根据右侧的初始化表达式自动推断变量的类型,使用 var 可以使代码更简洁,但也需要注意可读性

Q:为什么用"Var"

A:不用声明一个相对应参数的函数

Q:为什么结果递增了?

A:虽然number变量是在makeCounter函数内部定义的,但由于lambda表达式捕获了这个变量

所以即使在makeCounter函数执行完毕后,number变量仍然存在并且可以被访问和修改

图示流程:

闭包说白了就是可以利用lambda表达式的特性,抓住中间变量,从而不释放掉其内存

使得其变量值保留下来

相关推荐
不是万能的豆学长4 小时前
filetidy 文件整理助手:一键归类 + 规范重命名(Python 零依赖单文件工具)
大数据·开发语言·python·技术美术
懂点Tech8 小时前
ctfshow MISC入门图片篇(信息附加):misc41解题思路
开发语言·python
catchadmin9 小时前
PHP 8.7 协程新提案 让跨协程代码共享请求身份
开发语言·php
念何架构之路10 小时前
go-grpc设计思想
开发语言·后端·golang
酷炫码神10 小时前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
Elastic 中国社区官方博客11 小时前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn18811 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn12 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
传奇开心果编程13 小时前
【Rust入门练中学】第5课:引用与借用
开发语言·rust·引用·编程语言理论·通用编程语言·借用
qetfw13 小时前
Bash 变量:export、位置参数与默认值展开验证
linux·开发语言·chrome·bash