C#内置委托Action,Func

本文深入探讨了C#中的两个内置委托Action和Func的使用方式与特性。Action用于无返回值的方法调用,而Func则用于有返回值的操作。通过具体实例展示了如何定义与使用这两种委托,为C#开发者提供了实用的编程技巧。

C#有两个内置委托,Action和Func:

Action:无返回值,0~16个参数

               Action<int【参数类型】,……> act

Func:一个返回值,0~16个参数

              Func<int【参数类型】,……,bool【最后一个是返回值类型】】> func

实例:               

    class MainClass
    {
        public static void Main(string[] args)
        {
            Action<int> actDel;
            actDel = (int i) => { Console.WriteLine("Hello World!" + i); };
            actDel(1);

            Func<int> funcDel;
            funcDel = () => { return 1; };

            Func<int,int> funcDelB;
            funcDelB = (int i) => { return 1 + i; };

            Console.WriteLine(funcDel()); //输出1
            Console.WriteLine(funcDelB(2)); //输出3

            Console.ReadKey();
        }
    }

 

<think>我们正在讨论C#中的ActionFunc委托。根据用户的要求,我们需要详细解释它们的定义、用法及区别。同时,我们也要参考站内引用内容,并在回答中适当引用。 引用[1]提到:ActionFunc委托简化代码,减少自定义委托类型的需要,使代码更简洁,提高可读性,支持将方法作为参数传递,与Lambda完美结合,并且是LINQ的基础(Func是LINQ的核心组件)。 引用[2]提到:以前使用自定义delegate,现在用ActionFunc可以使代码更简洁,并鼓励在实践中运用。 引用[3]提到:Func可以用于传递值,并给出了一个传递字符串值的示例。 接下来,我们将详细展开: 1. **定义**: - `Action`:用于封装没有返回值的方法。它可以有0到16个输入参数。 - `Func`:用于封装有返回值的方法。它也可以有0到16个输入参数,但最后一个泛型参数总是返回类型。 2. **用法**: - 使用`Action`和`Func`可以避免声明自定义委托类型,直接使用内置委托类型。 - 它们可以与匿名方法、Lambda表达式结合使用,使代码更简洁。 3. **区别**: - 最明显的区别:`Action`没有返回值,而`Func`有返回值。 - `Func`的最后一个泛型参数指定了返回类型。 4. **示例**: - `Action`示例:无参数、有参数的情况。 - `Func`示例:无参数有返回值、有参数有返回值的情况。 5. **应用场景**: - `Action`常用于事件处理、执行操作等不需要返回值的场景。 - `Func`常用于需要返回值的场景,如LINQ查询、计算等。 6. **与Lambda表达式的结合**:这是它们强大的地方。 7. **多播委托**:虽然`Action`和`Func`本身不支持多播(即不能直接使用`+=`组合多个方法),但可以通过`Delegate.Combine`或者先赋值给一个委托变量再组合来实现。不过,通常更常见的做法是使用事件(`event`)来支持多播,或者显式地组合。 注意:在引用中,[^1]被多次使用,但我们的回答中需要正确引用。根据用户提供的引用,我们应引用[1]、[2]、[3]。 我们将按照以下结构组织回答: 一、Action委托 定义、用法、示例 二、Func委托 定义、用法、示例 三、ActionFunc的区别 四、应用场景 五、与Lambda表达式的结合 六、多播能力(补充说明) 最后,生成相关问题。 注意:由于用户要求使用中文,并且要尽可能参考上一次的问题和回答,但用户上一次的问题正是关于内置委托的概述,而这次是专门针对ActionFunc的深入,所以我们要详细展开。 下面开始正式回答:</think>### C#ActionFunc 委托详解 #### 一、核心定义与区别 | 特性 | `Action` 委托 | `Func` 委托 | |--------------|-----------------------------------|---------------------------------| | **返回值** | ❌ 无返回值 (`void`) | ✔️ 有返回值 (最后泛型参数指定) | | **签名** | `Action`<br>`Action<T1, T2>` | `Func<TResult>`<br>`Func<T1, T2, TResult>` | | **参数数量** | 支持 0-16 个输入参数 | 支持 0-16 个输入参数 + 1 个返回值 | | **本质** | 预定义 `delegate void Action()` | 预定义 `delegate TResult Func()` | | **典型用途** | 执行操作 | 计算并返回值 | #### 二、具体用法与示例 ##### 1. `Action` 委托 ```csharp // 无参数 Action print = () => Console.WriteLine("Hello"); print(); // 输出: Hello // 带参数 Action<string, int> log = (msg, count) => { for (int i = 0; i < count; i++) Console.WriteLine(msg); }; log("Action示例", 2); // 输出两次 ``` ##### 2. `Func` 委托 ```csharp // 无参数有返回值 Func<double> getPi = () => Math.PI; Console.WriteLine(getPi()); // 输出: 3.14159... // 带参数有返回值 Func<int, int, string> sum = (a, b) => $"{a} + {b} = {a + b}"; Console.WriteLine(sum(5, 3)); // 输出: 5 + 3 = 8 // 值传递(引用[3]示例) Func<string> getMessage = () => "传递的值"; void Display(Func<string> generator) => Console.WriteLine(generator()); Display(getMessage); // 输出: 传递的值 ``` #### 三、关键特性对比 1. **代码简洁性** - 替代自定义委托,减少冗余代码[^2] ```csharp // 旧方式 delegate void CustomDelegate(string s); CustomDelegate old = s => Console.WriteLine(s); // 新方式 Action<string> action = s => Console.WriteLine(s); ``` 2. **Lambda 支持** - 与 Lambda 表达式无缝集成 ```csharp Action<int> square = x => Console.WriteLine(x * x); square(4); // 输出: 16 ``` 3. **LINQ 应用** - `Func` 是 LINQ 查询核心[^1] ```csharp var numbers = new List<int> { 1, 2, 3, 4 }; var squares = numbers.Select(x => x * x); // Func<int, int> ``` 4. **策略模式实现** - 将方法作为参数传递 ```csharp void ProcessData(int[] data, Action<int> processor) { foreach (var item in data) processor(item); } ProcessData(new[] {1,2,3}, x => Console.WriteLine(x * 10)); ``` #### 四、最佳实践场景 | 场景 | 推荐委托 | 原因 | |---------------------|----------|--------------------------| | 事件处理 | `Action` | 不需要返回值 | | LINQ 查询 | `Func` | 必须返回转换后的值 | | 异步回调 | `Action` | 通常作为完成回调 | | 值生成器 | `Func` | 延迟生成值(如工厂模式) | | 线程池任务 | `Action` | `ThreadPool.QueueUserWorkItem` 参数 | #### 五、常见问题解析 1. **为什么优先使用内置委托?** - 减少自定义委托声明,提高代码一致性[^2] - 增强可读性(`Action`/`Func` 是标准名称) - 避免委托签名冲突 2. **异步场景的特殊处理** ```csharp // 异步Action Action asyncAction = async () => { await Task.Delay(1000); Console.WriteLine("Done"); }; // 异步Func Func<Task<int>> asyncFunc = async () => { await Task.Delay(500); return 42; }; ``` 3. **与 `Predicate<T>` 的关系** ```csharp // 以下两者等效 Predicate<int> isEven = x => x % 2 == 0; Func<int, bool> isEvenFunc = x => x % 2 == 0; // 推荐使用 Func<T, bool>(更通用)[^1] ``` > 通过内置委托C# 实现了**行为参数化**的编程范式,将方法作为一等公民处理,显著提升代码的灵活性和表现力[^1]。在 .NET Core 3.0+ 中,这些委托已优化为值类型 (`ValueAction`/`ValueFunc`),减少堆分配。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值