.NET 核心:Func 与 Action 委托(从入门到实战)

在 .NET 开发中,委托(Delegate) 是实现"方法作为参数传递"的核心机制。而 FuncAction 是 .NET 框架内置的预定义泛型委托,几乎覆盖了 90% 的委托使用场景------不用再手动定义自定义委托,直接用它们就能高效实现"方法传参"。

一句话核心区分(新手必记):

Func:有返回值,核心是"算出结果"
Action:无返回值,核心是"执行动作"

本文从 定义 → 示例 → 实战场景 → 易错点 → 对比总结 五个维度,把 Func/Action 讲透,看完就能直接用在项目里。

一、核心定义与语法(新手友好版)

1. Action 委托:只做事,不返回

核心特征

  • 无返回值(返回类型为 void),仅执行逻辑(比如打印、日志、修改状态)
  • 支持 0 ~ 16 个输入参数(满足绝大多数业务场景)
  • 框架已预定义,无需手动写 delegate 关键字

基础语法(常用版)

csharp 复制代码
Action               // 无参数,仅执行动作
Action<T>            // 1个参数,无返回值
Action<T1, T2>       // 2个参数,无返回值
// 最多支持 Action<T1,T2,...,T16>

2. Func 委托:算结果,必返回

核心特征

  • 必须有返回值(无参版本也得返回),核心是"计算并产出结果"
  • 支持 0 ~ 16 个输入参数,最后一个泛型参数固定是返回值类型(新手最易混点)
  • 同样是框架预定义,开箱即用

基础语法(常用版)

csharp 复制代码
Func<TResult>        // 无参数,返回 TResult 类型结果
Func<T1, TResult>    // 1个参数,返回 TResult 类型结果
Func<T1, T2, TResult>// 2个参数,返回 TResult 类型结果
// 最多支持 Func<T1,T2,...,T16, TResult>

二、Action 委托实战示例(带详细注释)

示例代码(可直接复制运行)

csharp 复制代码
using System;

class ActionPracticalDemo
{
    static void Main()
    {
        // 1. 无参数 Action:执行简单动作(打印固定内容)
        Action printWelcome = () => Console.WriteLine("✅ 欢迎使用 Action 委托!");
        printWelcome(); // 调用:直接执行,无返回值
        
        // 2. 1个参数 Action:接收字符串,打印姓名
        Action<string> printUserName = name => 
            Console.WriteLine($"👤 用户名:{name}");
        printUserName("李四"); // 传入参数执行
        
        // 3. 2个参数 Action:接收两个整数,打印求和过程(仅输出,不返回结果)
        Action<int, int> printAddProcess = (num1, num2) => 
        {
            int sum = num1 + num2; // 仅内部使用,不返回
            Console.WriteLine($"🧮 {num1} + {num2} = {sum}");
        };
        printAddProcess(15, 25); // 传入两个参数执行
    }
}

控制台输出结果

text 复制代码
✅ 欢迎使用 Action 委托!
👤 用户名:李四
🧮 15 + 25 = 40

新手提示

Action 的"价值"体现在"执行动作的副作用"(比如修改控制台输出、写入日志文件、更新UI),而非返回数据。

三、Func 委托实战示例(带详细注释)

示例代码(可直接复制运行)

csharp 复制代码
using System;

class FuncPracticalDemo
{
    static void Main()
    {
        // 1. 无参数 Func:返回固定字符串(核心是"产出结果")
        Func<string> getSystemMessage = () => "✅ 欢迎使用 Func 委托!";
        string msg = getSystemMessage(); // 调用:接收返回值
        Console.WriteLine(msg);
        
        // 2. 2个参数 Func:计算两个整数的和,返回结果
        Func<int, int, int> calculateSum = (a, b) => a + b;
        int sumResult = calculateSum(15, 25); // 接收返回值
        Console.WriteLine($"🧮 求和结果:{sumResult}");
        
        // 3. 2个参数 Func:计算两个小数的乘积(多行逻辑版)
        Func<double, double, double> calculateProduct = (x, y) =>
        {
            // 可写复杂逻辑,最终必须返回值
            double product = x * y;
            return product;
        };
        double productResult = calculateProduct(4.5, 2.0);
        Console.WriteLine($"🔢 乘积结果:{productResult}");
    }
}

控制台输出结果

text 复制代码
✅ 欢迎使用 Func 委托!
🧮 求和结果:40
🔢 乘积结果:9

新手提示

Func 调用后必须接收返回值(或直接使用),如果只调用不处理返回值,就失去了 Func 的核心意义。

四、实际开发中的高频场景(LINQ + 业务逻辑)

Func 和 Action 最常用在 LINQ 查询、集合操作、异步编程、回调函数 中,以下是项目中最常见的示例:

示例代码(LINQ 实战)

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;

class LinqWithFuncAction
{
    static void Main()
    {
        // 模拟业务数据:商品列表
        List<Product> products = new()
        {
            new Product { Id = 1, Name = "手机", Price = 2999 },
            new Product { Id = 2, Name = "耳机", Price = 199 },
            new Product { Id = 3, Name = "电脑", Price = 5999 }
        };

        // 1. Func 场景:LINQ Where 筛选(需要返回布尔结果判断是否符合条件)
        Func<Product, bool> isExpensiveProduct = p => p.Price > 2000;
        var expensiveProducts = products.Where(isExpensiveProduct).ToList();
        Console.WriteLine("💰 高价商品:");
        foreach (var p in expensiveProducts)
        {
            Console.WriteLine($"- {p.Name}({p.Price}元)");
        }

        // 2. Action 场景:遍历集合执行动作(仅打印,无返回值)
        Action<Product> printProductInfo = p => 
            Console.WriteLine($"📦 商品:{p.Name},价格:{p.Price}元");
        Console.WriteLine("\n📋 所有商品:");
        products.ForEach(printProductInfo);
    }

    // 定义商品类(模拟业务实体)
    class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

控制台输出结果

text 复制代码
💰 高价商品:
- 手机(2999元)
- 电脑(5999元)

📋 所有商品:
📦 商品:手机,价格:2999元
📦 商品:耳机,价格:199元
📦 商品:电脑,价格:5999元

核心结论

  • LINQ 中 Where/Select/FirstOrDefault 等需要"返回判断/转换结果"的方法,底层都是 Func 委托;
  • 集合 ForEach、事件回调、日志记录等"只执行动作"的场景,优先用 Action 委托。

五、新手易错点提醒(避坑指南)

  1. Func 泛型参数顺序 :新手容易把返回值类型放错位置,记住「Func 的最后一个泛型参数永远是返回值」,比如 Func<int, string> 是"接收 int 参数,返回 string",而非反过来;
  2. Action 并非不能有逻辑内部的变量:Action 可以在内部定义变量、执行复杂逻辑,只是最终不返回值;
  3. 避免过度封装 :简单逻辑直接用 lambda 表达式(如示例中的 p => p.Price > 2000),无需单独定义委托变量,减少冗余代码。

六、Func vs Action 核心差异对比表

对比维度 Func 委托 Action 委托
返回值 必须有(最后一个泛型参数为返回类型) 无(返回 void)
泛型参数含义 前 N 个是输入参数,最后 1 个是返回值 所有参数都是输入参数,无返回值参数
核心用途 计算、筛选、转换(需要结果) 打印、日志、遍历(仅执行动作)
调用方式 接收返回值后使用 直接调用,无需接收返回值
常见场景 LINQ 查询、业务计算、条件判断 集合遍历、事件处理、日志记录

七、总结(面试 + 实战速记)

核心要点

  1. 选 Func:当你需要一段逻辑"产出结果"(比如计算、筛选、转换数据)时使用;
  2. 选 Action:当你只需要一段逻辑"执行动作"(比如打印、写日志、更新状态)时使用;
  3. 新手技巧:写代码前先问自己「这段逻辑需要返回值吗?」------ 需要用 Func,不需要用 Action。

实战建议

  • 日常开发优先使用框架预定义的 Func/Action,而非手动定义 delegate,减少代码量;
  • LINQ 操作中,Func 是"主角",Action 仅用于遍历输出;
  • 异步编程中(如 Func<Task>、Action),核心区分逻辑和同步场景一致。

相关推荐
peixiuhui8 分钟前
Iotgateway技术手册-3. 架构设计
.net·iot·核心板·iotgateway·开源网关·arm工控板
flysh051 小时前
关于C#编程中的async / await关键字
开发语言·c#
m5655bj1 小时前
使用 C# 将 RTF 文档转换为 PDF 格式
pdf·c#
李建军12 小时前
界止签章宗地号替换工具
c#
qq_4252633212 小时前
.net开发框架和语言
c#
武藤一雄12 小时前
C# 关于多线程如何实现需要注意的问题(持续更新)
windows·后端·microsoft·c#·.net·.netcore·死锁
flysh0513 小时前
C# 架构设计:接口 vs 抽象类的深度选型指南
开发语言·c#
flysh0513 小时前
C# 中类型转换与模式匹配核心概念
开发语言·c#
故事不长丨15 小时前
C#字典(Dictionary)全面解析:从基础用法到实战优化
开发语言·c#·wpf·哈希算法·字典·dictionary·键值对
wtsolutions18 小时前
Sheet-to-Doc占位符系统详解:让数据自动填入Word指定位置
开发语言·c#