您的位置:首页 >c#如何使用Action和Func_c#Action和Func从入门到精通教程
发布于2026-05-03 阅读(0)
扫一扫,手机访问

开门见山,先说一个核心判断:Action 和 Func 压根不是什么需要“学透”才能用的高级概念。恰恰相反,它们是C#世界里最基础、最常用的委托类型,日常开发中处理事件、异步回调、LINQ查询或是依赖注入配置时,几乎天天都会打照面。真正让开发者感到困惑的,往往不是语法本身,而是两个更实际的问题:“眼下这个场景,我到底该用哪个?” 以及 “Func的参数顺序,到底该怎么记才不容易错?”。
Action,而不是自己写委托?简单来说,Action 就是那个“只负责执行、不关心返回值”的委托标准件。当你需要定义一个 delegate void DoSomething(string s, int i) 时,与其从头手写,不如直接使用 Action。编译器在背后已经为你做好了所有映射,而且整个.NET基础库(比如 List 方法、Task.Run 方法)都认它,兼容性和通用性直接拉满。
button.Click += (s, e) => { ... },其本质就是 Action 的一种变体;而 Task.Run(() => Console.WriteLine("done")) 里用到的,正是无参数的 Action。Action 最多支持16个泛型参数(从 Action 到 Action)。一旦超过这个数量,抱歉,你就得回归老路,自己动手定义委托了。public delegate void LogHandler(string msg);),否则,自己手写 delegate 纯属增加无谓的代码量。Func 的返回值类型总在最后,这是硬规则关于 Func,有一条铁律必须刻在脑子里:它的泛型参数列表中,最后一个类型参数,一定是返回值类型,前面的所有类型才是输入参数。这个顺序一旦搞错,编译器会毫不客气地抛出 CS0411 错误。
Func。如果一不小心写成了 Func,语义就完全反了,变成了“输入string,返回int”。Func。比如,Func 表示一个调用后会返回字符串的方法。这种形式在实现延迟计算时特别有用,例如:var lazyName = new Lazy(() => GetNameFromDb()); 。Func 必须要有返回值类型。所以,Func 是非法语法。如果你的方法什么都不想返回,请直接去找 Action。使用lambda表达式来创建 Action 或 Func 时,如果lambda内部引用了外部的局部变量,一个经典的“闭包陷阱”可能正在等着你。比如下面这个例子:
var actions = new List(); for (int i = 0; i < 3; i++) { actions.Add(() => Console.WriteLine(i)); // 小心!这里全部会输出 3! } foreach (var a in actions) a();
i 的引用,而不是在循环每个迭代时的瞬时值。当循环结束时,i 的值已经变成了3,此时所有存储在列表中的Action再去读取 i,看到的自然都是这个最终值。for (int i = 0; i < 3; i++) { int localI = i; actions.Add(() => Console.WriteLine(localI)); }foreach 循环的迭代变量默认已经按值捕获了,但这个“福利”并没有惠及传统的 for 循环,后者仍需手动处理。话说回来,还有一个容易被忽略的高级特性——委托的协变与逆变。举个例子,Func 能直接赋值给 Func 吗?答案是不能。但反过来,Func 却可以赋值给 Func(因为string是object的子类,返回值类型支持协变)。这类细节在平常简单的委托调用中并不显眼,可一旦涉及到复杂的泛型委托转换或者框架接口设计时,它们就会突然变得至关重要。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9