Action<T>和Func<T>泛型委托,委托,泛型,匿名函数,Lambda表达式的综合使用

本文介绍了C#中Action<T>和Func<T>泛型委托的使用,强调了它们与普通委托的区别。通过实例展示了如何利用泛型委托、匿名方法和Lambda表达式实现更灵活的代码。文章总结了泛型委托的优势,并提供了事件(event)和委托(delegate)结合使用的示例。

前言

在上篇文章C#中委托(delegate)和多播委托的理解中已经基本了解了委托的用法。
由于委托封装的方法我们不一定知道其传入的参数和返回值,例如之前说的的排序方法—————在对象的排序算法中,需要对对象进行比较,而不同对象比较的方法不同,所以比较两个对象的方法的引用可以作为参数传递到排序算法中,这个时候就需要传递方法。
当我们要生成一个封装比较对象的方法的委托时,我们并不知道该方法传入对象是什么,所有我们必须引入泛型的概念来辅助委托的使用。

Action<T>Func<T>泛型委托

除了为每个参数和返回类型定义一个新委托类型外(基本的委托定义方法),还有就是使用Action<T>Func<T>定义委托,Action<T>委托表示引用一个void返回类型的方法,且最多可以传递16种参数;Func<T>类似,但允许调用带返回值的方法。

注意对比普通委托泛型委托的定义和使用的区别。

普通委托的定义和使用的博客

泛型委托的定义和使用:
对于上篇加减的例子,可以直接将Func<int, int,int>类型的委托作为参数:

public int numMethod(int num1,
<think>嗯,用户之前问过关于C#中=>符号的用法,特别是不同委托如FuncAction中的使用区别。现在他们想更深入了解在FuncAction中使用=>语法的区别示例。我需要先回顾一下之前的回答,确保这次回答保持一致,同时补充更多细节。 首先,用户可能已经了解=>用于lambda表达式表达式体定义,但这次重点在委托。FuncAction的主要区别在于返回值,Func有返回值,而Action没有。需要明确这两者的不同,并通过示例展示如何用=>语法来创建对应的lambda表达式。 在之前的回答中,已经提到了FuncAction的简单例子,比如Func<int, int>Action<string>。现在需要更详细地区分两者,可能包括多参数的情况,以及如何处理void返回类型。 另外,用户可能想知道在实际编程中如何选择使用Func还是Action,或者是否有性能上的差异。不过根据问题,主要还是集中在语法上的区别示例,所以需要重点放在这两个方面。 还要注意用户提到的“尽可能多的参考用户上一次的问题回答”,所以需要确保引用之前的例子,并在此基础上扩展。例如,之前的回答中有一个Func的例子是计算平方,而Action的例子是记录日志。可以沿用这些例子,并进一步展示更多参数的情况,比如Func<int, int, int>Action<int, string>等。 另外,用户可能对闭包或变量捕获感兴趣,这在之前的回答中也有提到,但这次问题可能不需要深入讨论,除非直接相关。不过如果有涉及委托使用外部变量,可以简要提及。 最后,要确保示例代码正确,符合C#语法,并且用中文清晰解释每个部分。可能还需要提到类推断,因为在FuncAction中使用lambda时,参数类通常可以省略,由编译器推断,但有时候需要显式声明,尤其是在重载的情况下。 总结下来,回答的结构应该是先解释FuncAction的区别,然后分别给出示例,展示如何使用=>语法,最后可能总结两者的适用场景。同时要注意引用之前的注释,比如闭包的问题,但这次的问题可能不需要深入讨论,所以放在注意事项里即可。</think>### C# 中 `=>` 语法在 `Func<>` `Action<>` 委托中的区别与示例 在 C# 中,`Func<>` `Action<>` 是两种常用的委托,结合 `=>` 语法可实现简洁的匿名函数定义。它们的核心区别在于 **返回值类**: | 委托 | 返回值 | 典用途 | `=>` 语法要求 | |------------|----------|------------------------|-----------------------| | `Func<>` | **有** | 需要返回值的逻辑 | 表达式必须返回值 | | `Action<>` | **无** | 执行操作(无返回值) | 表达式无需返回值 | --- ### 一、`Func<>` 委托与 `=>` 语法 `Func<>` 委托的最后一个参数表示返回值类。 **语法示例**: ```csharp Func<int, int, string> func = (a, b) => (a + b).ToString(); ``` #### 典场景 1. **单参数返回值** ```csharp Func<int, bool> isEven = x => x % 2 == 0; Console.WriteLine(isEven(4)); // 输出 True ``` 2. **多参数计算** ```csharp Func<double, double, double> power = (baseNum, exponent) => Math.Pow(baseNum, exponent); Console.WriteLine(power(2, 3)); // 输出 8 ``` 3. **结合 LINQ 的复杂逻辑** ```csharp Func<int, string> gradeClassifier = score => score >= 90 ? "A" : score >= 80 ? "B" : "C"; ``` --- ### 二、`Action<>` 委托与 `=>` 语法 `Action<>` 委托无返回值,常用于执行操作。 **语法示例**: ```csharp Action<string> log = message => Console.WriteLine($"[LOG] {message}"); ``` #### 典场景 1. **单参数操作** ```csharp Action<string> printUpper = s => Console.WriteLine(s.ToUpper()); printUpper("hello"); // 输出 "HELLO" ``` 2. **多参数操作** ```csharp Action<int, string> repeatPrint = (count, text) => { for (int i = 0; i < count; i++) Console.WriteLine(text); }; repeatPrint(3, "C#"); // 输出 3 次 "C#" ``` 3. **事件处理** ```csharp button.Click += (sender, args) => MessageBox.Show("Button clicked!"); ``` --- ### 三、关键区别与选择原则 | 特性 | `Func<>` | `Action<>` | |---------------------|-----------------------------------|----------------------------------| | **返回值** | 必须明确返回值 | 无返回值 | | **表达式体内容** | 必须为返回值的表达式 | 可以是任意语句(如赋值、循环) | | **常见用途** | 计算、转换、条件判断 | 日志、修改状态、触发操作 | | **委托定义** | `Func<T1, T2, ..., TResult>` | `Action<T1, T2, ...>` | #### 选择原则: - 需要返回值时用 `Func<>`(如数据处理、条件筛选) - 仅需执行操作时用 `Action<>`(如事件回调、状态更新) --- ### 四、高级用法示例 1. **`Func<>` 返回值类推断** ```csharp var parse = (string s) => int.Parse(s); // C# 10+ 支持隐式类 ``` 2. **`Action<>` 捕获外部变量(闭包)** ```csharp int counter = 0; Action increment = () => counter++; increment(); Console.WriteLine(counter); // 输出 1 ``` > **注意**:闭包可能导致变量生命周期延长[^1]。 3. **委托组合** ```csharp Action<string> greet = name => Console.WriteLine($"Hello, {name}"); Action<string> warn = name => Console.WriteLine($"Warning: {name} invalid"); Action<string> combined = greet + warn; combined("Alice"); // 依次执行 greet warn ``` --- ### 五、常见错误与解决方法 1. **返回值不匹配** ```csharp // 错误:Func<int> 需要返回值,但表达式无返回 Func<int> invalid = () => Console.WriteLine("Error"); // 正确:改用 Action Action valid = () => Console.WriteLine("OK"); ``` 2. **参数类不明确** ```csharp // 错误:无法推断参数类 var ambiguous = (x) => x * 2; // 正确:显式声明类 Func<int, int> clear = x => x * 2; ``` --- ### 相关问题 1. 如何在 `Func<>` 委托中处理异常? 2. `Action<>` 委托是否支持异步操作(如 `async/await`)? 3. 委托与接口在 C# 中的使用场景有何区别?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值