商城首页欢迎来到中国正版软件门户

您的位置:首页 >c#如何使用Action和Func_c#Action和Func从入门到精通教程

c#如何使用Action和Func_c#Action和Func从入门到精通教程

  发布于2026-05-03 阅读(0)

扫一扫,手机访问

C#中的Action与Func:从“天天见”到“真正会用”

c#如何使用Action和Func_c#Action和Func从入门到精通教程

开门见山,先说一个核心判断:ActionFunc 压根不是什么需要“学透”才能用的高级概念。恰恰相反,它们是C#世界里最基础、最常用的委托类型,日常开发中处理事件、异步回调、LINQ查询或是依赖注入配置时,几乎天天都会打照面。真正让开发者感到困惑的,往往不是语法本身,而是两个更实际的问题:“眼下这个场景,我到底该用哪个?” 以及 “Func的参数顺序,到底该怎么记才不容易错?”

什么时候必须用 Action,而不是自己写委托?

简单来说,Action 就是那个“只负责执行、不关心返回值”的委托标准件。当你需要定义一个 delegate void DoSomething(string s, int i) 时,与其从头手写,不如直接使用 Action。编译器在背后已经为你做好了所有映射,而且整个.NET基础库(比如 List.ForEach 方法、Task.Run 方法)都认它,兼容性和通用性直接拉满。

  • 典型应用场景:按钮的点击事件 button.Click += (s, e) => { ... },其本质就是 Action 的一种变体;而 Task.Run(() => Console.WriteLine("done")) 里用到的,正是无参数的 Action
  • 注意参数上限:系统预定义的 Action 最多支持16个泛型参数(从 ActionAction)。一旦超过这个数量,抱歉,你就得回归老路,自己动手定义委托了。
  • 给个实用建议:除非你需要多次复用同一个委托签名,并且希望给它起一个清晰易懂的名字(例如 public delegate void LogHandler(string msg);),否则,自己手写 delegate 纯属增加无谓的代码量。

Func 的返回值类型总在最后,这是硬规则

关于 Func,有一条铁律必须刻在脑子里:它的泛型参数列表中,最后一个类型参数,一定是返回值类型,前面的所有类型才是输入参数。这个顺序一旦搞错,编译器会毫不客气地抛出 CS0411 错误。

  • 反面教材:想表达“输入一个int,返回一个string”,正确的写法是 Func。如果一不小心写成了 Func,语义就完全反了,变成了“输入string,返回int”。
  • 无参但有返回值:这时候就用 Func。比如,Func 表示一个调用后会返回字符串的方法。这种形式在实现延迟计算时特别有用,例如:var lazyName = new Lazy(() => GetNameFromDb());
  • 一个关键限制Func 必须要有返回值类型。所以,Func 是非法语法。如果你的方法什么都不想返回,请直接去找 Action

传参时捕获变量要注意生命周期

使用lambda表达式来创建 ActionFunc 时,如果lambda内部引用了外部的局部变量,一个经典的“闭包陷阱”可能正在等着你。比如下面这个例子:

var actions = new List();
for (int i = 0; i < 3; i++) {
    actions.Add(() => Console.WriteLine(i)); // 小心!这里全部会输出 3!
}
foreach (var a in actions) a();
  • 问题根源:lambda表达式捕获的是变量 i 的引用,而不是在循环每个迭代时的瞬时值。当循环结束时,i 的值已经变成了3,此时所有存储在列表中的Action再去读取 i,看到的自然都是这个最终值。
  • 标准修复方案:在循环体内部声明一个局部变量,让lambda捕获这个“快照”。for (int i = 0; i < 3; i++) { int localI = i; actions.Add(() => Console.WriteLine(localI)); }
  • 需要留意:在C# 5及更高版本中,foreach 循环的迭代变量默认已经按值捕获了,但这个“福利”并没有惠及传统的 for 循环,后者仍需手动处理。

话说回来,还有一个容易被忽略的高级特性——委托的协变与逆变。举个例子,Func 能直接赋值给 Func 吗?答案是不能。但反过来,Func 却可以赋值给 Func(因为string是object的子类,返回值类型支持协变)。这类细节在平常简单的委托调用中并不显眼,可一旦涉及到复杂的泛型委托转换或者框架接口设计时,它们就会突然变得至关重要。

本文转载于:https://www.php.cn/faq/2315640.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。
  • php-fpm在Ubuntu中如何优化连接数 正版软件
    php-fpm在Ubuntu中如何优化连接数
    在Ubuntu中优化PHP-FPM连接数的实用指南 想让你的PHP应用在高并发下依然流畅响应吗?优化PHP-FPM的连接数配置是关键一步。通过调整几个核心参数,就能显著提升性能和资源利用率。下面这份操作指南,将带你一步步完成配置。 1. 定位并编辑PHP-FPM配置文件 一切调整都始于配置文件。通常
    7分钟前 0
  • php-fpm在Ubuntu中如何配置日志级别 正版软件
    php-fpm在Ubuntu中如何配置日志级别
    在Ubuntu中配置PHP-FPM日志级别 给PHP-FPM配置合适的日志级别,是排查线上问题、掌握应用运行状态的关键一步。下面这个流程,能帮你快速完成设置。 1. 打开PHP-FPM配置文件 配置文件通常位于 /etc/php/{version}/fpm/pool.d/www.conf,这里的 {
    8分钟前 0
  • php-fpm在Ubuntu中如何调整内存限制 正版软件
    php-fpm在Ubuntu中如何调整内存限制
    在Ubuntu中调整PHP-FPM内存限制的完整指南 处理PHP应用时,内存限制是个绕不开的话题。尤其在Ubuntu服务器上运行PHP-FPM时,合理配置内存上限,既能保障应用稳定运行,又能避免资源浪费。下面这份操作指南,将带你一步步完成配置调整。 第一步:打开终端 一切操作都从终端开始。这是你与服
    8分钟前 0
  • php-fpm在Ubuntu中如何设置监听端口 正版软件
    php-fpm在Ubuntu中如何设置监听端口
    在Ubuntu中设置PHP-FPM监听端口 想让PHP-FPM换个姿势工作,从监听Unix套接字切换到监听TCP端口?这个调整在需要跨容器通信或特定网络配置的场景下很常见。过程其实很直接,核心就是修改一个配置文件。下面咱们一步步来。 第一步:打开终端 一切操作的基础,从打开你的终端开始。 第二步:定
    8分钟前 0
  • nginx 如何解析php文件php-fpm的解释 正版软件
    nginx 如何解析php文件php-fpm的解释
    nginx 如何解析php文件php-fpm的解释 要理清这个过程,不妨先从nginx的配置入手。通常,我们会在nginx的配置文件(比如 /usr/local/nginx/conf/nginx.conf)里看到类似下面这样的段落: location ~ \.php { root /nginx; f
    9分钟前 0