func和action是.net预定义的开箱即用委托类型,非需手动封装;func参数列表末位必为返回值类型,action无返回值;超16参数或需语义化命名时才用自定义delegate;闭包捕获引用是常见坑点。

直接说结论:不用学“泛型委托封装”,Func 和 Action 就是 .NET 预装好的、开箱即用的委托类型,不是要你手动封装的东西;真正卡住人的,是参数顺序记混、闭包踩坑、以及该用哪个时拿不定主意。
Func 的参数顺序为什么总写错?
因为 Func 的泛型参数列表里,最后一个一定是返回值类型,前面全是输入参数——这个顺序是硬编码进编译器里的,写反就报 CS0411 错误。
-
Func<int string></int>表示「输入int,返回string」✅ -
Func<string int></string>表示「输入string,返回int」✅(但语义完全变了) -
Func<int void></int>是非法的❌——void不能当泛型参数,这时候必须换Action<int></int> - 无参有返回?用
Func<string></string>,不是Func(后者语法不存在)
Action 和自定义 delegate 到底差在哪?
差在编译器认不认识。你写 delegate void LogHandler(string msg, int level);,再传给 List<t>.ForEach</t> 或 Task.Run,会直接编译失败——因为这些 API 只接受 Action<t></t> 系列。
-
Action是微软定的“通用协议”,所有基础库都按它签名设计 - 手写
delegate只在两种情况下值得:需要重用同一签名多次 + 要给它起个有意义的名字(比如public delegate void RetryPolicy(int attempt);) - 参数超 16 个?
Action<t1></t1>不存在,得自己写委托,但现实中几乎没人遇到
for 循环里存 Action/Func 为什么会全输出同一个值?
这是闭包捕获变量引用导致的,不是委托本身的问题,但新手十次有九次栽在这儿。
- 错误写法:
for (int i = 0; i Console.WriteLine(i));→ 全部输出3 - 原因:
i是循环变量,lambda 捕获的是它的引用,不是每次迭代的快照 - 修复方式:在循环体内声明新变量,强制捕获当前值:
for (int i = 0; i Console.WriteLine(localI)); } - 注意:
foreach在 C# 5+ 已修复此问题,但for仍需手动处理
最容易被忽略的其实是协变逆变——比如 Action<object></object> 能安全接收 Action<string></string>,但反过来不行;这种隐式转换在泛型约束和接口实现里才真正显出价值,日常写业务逻辑时反而容易因过度依赖它而写出难调试的类型推导链。











