[C#基础]Func和Action学习

本文详细介绍了 C# 中的委托概念,包括 Action 和 Func 的使用方法,并通过实例展示了如何利用 Lambda 表达式简化委托的定义与使用。

目录

委托

Action

Func

总结

委托

委托的那些事

关于委托的基本定义,在很久之前的这篇文章中,有个简单的介绍。稍微回顾一下。

委托是c#中类型安全的,可以订阅一个或多个具有相同签名方法的函数指针

声明委托的方式:delegate 返回值类型 委托类型名(参数)

例如:

1  delegate void Say(string strContent);

如果想使用该委托,需要一个对应的方法。

1  /// <summary>
2 /// 委托对应方法
3 /// </summary>
4 /// <param name="strContent"></param>
5 private static void ChineseSay(string strContent)
6 {
7         Console.WriteLine(strContent);
8 }

简单的调用:

1         static void Main(string[] args)
2         {
3             Say sy = new Say(ChineseSay);//方式一
4             Say say = ChineseSay;//方式二
5             sy("您好");
6             say("您好");
7             Console.Read();
8         }

上面介绍了,平时用委托的一般方式,先声明委托,然后再去使用,有点麻烦,.net中有已经定义好的委托类型,可以拿来直接用。

Action

Action委托有两种方式:无参数无返回值的委托,有至少一个最多16个的参数无返回值的泛型委托。

1     // 摘要: 
2     //     封装一个方法,该方法不具有参数并且不返回值。
3     [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
4     public delegate void Action();

Action泛型委托根据输入参数个数的不同,Action委托有十六个重载

用Action改写上面的例子,上面的例子中委托是无返回值有string类型的输入参数,所以使用Action的泛型版本。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Action<string> SayHello = new Action<string>(ChineseSay);//方式一
 6             Action<string> SayName = ChineseSay;//方式二
 7             Action<string> SayAge = s => Console.WriteLine("我今年{0}岁了", s);//方式三
 8             SayHello("您好");
 9             SayName.Invoke("我叫Wolfy");
10             IAsyncResult result = SayAge.BeginInvoke("27", CallBack, "爱好女");
11             if (result.IsCompleted)
12             {
13                 SayAge.EndInvoke(result);
14             }
15             Console.Read();
16         }
17 
18         private static void CallBack(IAsyncResult ar)
19         {
20             Console.WriteLine("介绍完毕,忘了,我{0},我不搞基",ar.AsyncState.ToString());
21         }
22         /// <summary>
23         /// 委托对应方法
24         /// </summary>
25         /// <param name="strContent"></param>
26         private static void ChineseSay(string strContent)
27         {
28             Console.WriteLine(strContent);
29         }
30     }

结果:

上面代码中,列出了Action泛型委托的使用方式,以及使用Lambda的方式,Action也可以使用匿名方法,选择一种自己上手的来用即可。

Func

如果要用有输入参数,有返回值的委托,那么Func委托将满足你的要求。

Func泛型委托,可以没有输入参数,但必须有返回值。根据输入参数的多少有17个重载。

in:输入参数

out:输出参数,也就是返回值。

一个案例

输入名字,年龄,性别,对年龄,性别,姓名进行修改后输出。

 1     public class Person
 2     {
 3         public string Name { set; get; }
 4         public int Age { set; get; }
 5         public bool Gender { set; get; }
 6         /// <summary>
 7         /// 重写tostring方法,方便输出结果
 8         /// </summary>
 9         /// <returns></returns>
10         public override string ToString()
11         {
12             return Name + "\t" + Age + "\t" + Gender;
13         }
14     }
15     class Program
16     {
17         static void Main(string[] args)
18         {
19             Func<Person, Person> funcUpdateAge = new Func<Person, Person>(UpdateAge);
20             Func<Person, Person> funcUpdateAge2 = UpdateAge;
21             Func<Person, Person> funcUpdateGender = (p1) => { p1.Gender = false; return p1; };//lambda表达式方式
22             Func<Person, Person> funUpdateName = delegate(Person p2)//匿名方法
23             {
24                 p2.Name = "Wolfy2";
25                 return p2;
26             };
27             Person p = new Person() { Name = "Wolfy", Age = 24, Gender = true };
28             Person result = funcUpdateAge(p);
29             Console.WriteLine(result.ToString());
30             Console.WriteLine(funcUpdateGender(p).ToString());
31             Console.WriteLine(funUpdateName(p).ToString());
32             Console.Read();
33         }
34         static Person UpdateAge(Person p)
35         {
36             p.Age = 25;
37             return p;
38         }
39 
40     }

结果:

Func泛型委托,可以没有输入参数,但是必须有输出参数。

总结

Action:无参数无返回值委托。

Action<T>:泛型委托,无返回值,根据输入参数的个数不同有十六个重载。

Func< out T>:无输入参数,有返回值。

Func<in T,out T>:有输入参数,有返回值,根据输入参数个数不同,有十六个重载。

Action和Func中可以使用Lambda和匿名方法处理方法体内逻辑。

(天太热,人很躁,在你不知道做什么的时候,不如静下来对基础进行查漏补缺,能掌握一点是一点,别总抱怨,总烦躁,就算你抱怨,烦躁,最后该完成的事还是你的,不多不减就在那里,夏天这天气,太烦躁,啥事都不做了吗?难道敲代码不是一件开心的事吗?)

<think>我们正在讨论C#中的FuncAction委托。根据引用,我们可以总结如下:1.**Func委托**:用于表示有返回值的方法。它可以带有0到16个输入参数,最后一个类型参数是返回类型。例如:-`Func<string>`:无参数,返回string。-`Func<int,string>`:一个int参数,返回string。2.**Action委托**:用于表示没有返回值(void)的方法。它可以带有0到16个输入参数。例如:-`Action`:无参数,无返回值。-`Action<int>`:一个int参数,无返回值。区别:**Func有返回值,Action没有返回值。**引用中的例子:-引用[1]:明确指出ActionFunc的区别在于Func有返回值,而Action没有。-引用[2]:展示了一个Func的例子,`Func<string>RetBook`,它返回一个字符串。-引用[3]:展示了Action的用法,例如`Actionact``Action<int>act`,它们没有返回值。-引用[4]:提到Predicate<T>类似于Func<T,bool>,但这里主要强调FuncAction的通用性。因此,我们可以这样回答用户的问题:在C#中,FuncAction都是预定义的委托类型,它们的主要区别在于:-**Func**总是有返回值,其签名中最后一个类型参数指定返回值类型。-**Action**没有返回值(即返回void)。例如:-使用Func:当你需要封装一个返回数值的方法时。-使用Action:当你需要封装一个执行操作但不返回值的方法时。下面提供一些示例代码:**Func示例:**```csharp//定义一个返回字符串的方法staticstringGetMessage(){return"Hello,World!";}//使用Func委托Func<string>messageFunc=GetMessage;stringresult=messageFunc();//调用委托,返回"Hello,World!"```**Action示例:**```csharp//定义一个没有返回值的方法,打印消息staticvoidPrintMessage(stringmessage){Console.WriteLine(message);}//使用Action委托Action<string>printAction=PrintMessage;printAction("Hello,World!");//调用委托,打印消息```另外,还可以使用lambda表达式来初始化这些委托:```csharpFunc<int,int,int>add=(a,b)=>a+b;intsum=add(3,5);//返回8Action<string>greet=name=>Console.WriteLine($"Hello,{name}!");greet("Alice");//打印"Hello,Alice!"```总结:选择Func还是Action取决于被封装的方法是否有返回值。§§相关问题§§1.在C#中,如何使用lambda表达式初始化FuncAction委托?2.FuncAction委托最多支持多少个参数?3.除了FuncActionC#中还有哪些常用的委托类型?4.在异步编程中,FuncAction如何与asyncawait一起使用?</think>### C#FuncAction的区别详解 在C#中,**Func****Action**都是预定义的委托类型,核心区别在于**返回值**: - **Func**:**有返回值**的委托(至少1个泛型参数,最后一个为返回类型) - **Action**:**无返回值**(void)的委托(泛型参数仅用于输入) #### 一、核心差异对比表 | 特性 | Func委托 | Action委托 | |--------------|-----------------------------|-----------------------------| | **返回值** | 必有返回值(不可为void) | 无返回值(void) | | **签名示例** | `Func<in T, out TResult>` | `Action<in T1, in T2>` | | **参数上限** | 最多16输入参数 + 1返回参数 | 最多16输入参数 | | **使用场景** | 需要结果的计算操作 | 执行无返回的操作 | #### 二、代码示例解析 1. **Func委托示例**(带返回值) ```csharp // 定义返回字符串的方法 static string GetBook() => "C#高级编程"; // 使用Func封装 Func<string> bookFunc = GetBook; Console.WriteLine(bookFunc()); // 输出:"C#高级编程" // 带参数的Func Func<int, int, string> sumFunc = (a, b) => $"结果:{a + b}"; Console.WriteLine(sumFunc(3, 5)); // 输出:"结果:8" ``` 2. **Action委托示例**(无返回值) ```csharp // 定义无返回值方法 static void LogMessage(string msg) => Console.WriteLine($"日志:{msg}"); // 使用Action封装 Action<string> logAction = LogMessage; logAction("功能启动"); // 输出:"日志:功能启动" // 带多参数的Action Action<int, string> printAction = (id, name) => Console.WriteLine($"ID:{id}, 姓名:{name}"); printAction(101, "张三"); ``` #### 三、关键区别点 1. **返回值约束** - Func的最后一个泛型参数**必须**是返回类型 ```csharp Func<int, bool> isValid = x => x > 0; // 返回bool ``` - Action**禁止**声明返回类型 ```csharp Action<string> print = Console.Write; // 无返回值 ``` 2. **Lambda表达式差异** ```csharp // Func需显式返回值 Func<int> getRandom = () => new Random().Next(); // Action不能有return语句 Action reset = () => Console.Clear(); ``` 3. **异步支持** 两者都支持异步操作,但需注意返回类型: ```csharp // 异步Func(返回Task<string>) Func<Task<string>> asyncFunc = async () => { await Task.Delay(100); return "异步完成"; }; // 异步Action(返回Task) Action asyncAction = async () => await Task.Delay(100); ``` #### 四、实际应用场景 - **Func适用**:数据转换、条件判断、工厂模式创建对象 ```csharp Func<User, string> getName = user => user.FirstName + " " + user.LastName; ``` - **Action适用**:事件处理、日志记录、状态修改 ```csharp button.Click += (sender, e) => MessageBox.Show("已点击"); ``` > 引用说明:FuncAction简化了委托的使用,避免了显式定义`delegate`关键字[^3]。两者的本质区别在于封装的方法是否需要返回值[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值