Action和Func和Predicate

Action和Func和Predicate

Action和Func和Predicate

Action、Func、Predicate本质上都是委托

Action是无返回值的泛型委托

Action 表示无参,无返回值的委托

Action<int,string> 表示有传入参数int,string无返回值的委托

Func是有返回值的泛型委托

Func<int> 表示无参,返回值为int的委托

Func<object,string,int> 表示传入参数为object, string 返回值为int的委托

Predicate 是返回bool型的谓语泛型委托

Predicate<int> 表示传入参数为int 返回bool的委托

Action示例: class Program
{
static Action A1;
static Action<string> A2;

static void Main(string[] args)
{
A1 = new Action(HelloWorld1);
A1();

A2 = new Action<string>(HelloWorld2);
A2("Jimmy");

//用Lambda表达式给委托赋值。
A2 = (string name) => { Console.WriteLine("你好,{0}!", name); };
A2("杨俊明");

//用匿名方法给委托赋值。
A2 = delegate(string name) { Console.WriteLine("我就是委托,{0} 你说对吗?", name); };
A2("菩提树下的杨过");

Console.Read();
}

static void HelloWorld1()
{
Console.WriteLine("Hello World!");
}

static void HelloWorld2(string name)
{
Console.WriteLine("Hello,{0}!", name);
}

}

Func示例:class Program
{
static Func<string> F;
static Func<DateTime, string> F2;

static void Main(string[] args)
{
F = new Func<string>(HelloWorld1);
Console.WriteLine(F());

F2 = new Func<DateTime, string>(HelloWorld2);
Console.WriteLine(F2(DateTime.Now));

Console.Read();
}

static string HelloWorld1()
{
return "Hello World!";
}


static string HelloWorld2(DateTime time)
{
return string.Format("Hello World,the time is {0}.", time);
}

}
Observer设计模式

Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。

Observer模式主要包括如下两类对象:

Subject:被监视对象,它往往包含着其他对象所感兴趣的内容。在本范例中,热水器就是一个被监视对象,它的temprature字段就是其他对象感兴趣的内容,当这个字段的值大于95时时,会不断把数据发给监视它的对象。

Observer:监视者,它监视Subject,当Subject中的某件事发生的时候,会告知Observer,而Observer则会采取相应的行动。在本范例中,Observer有警报器和显示器,它们采取的行动分别是发出警报和显示水温。

假设热水器由三部分组成:heater(热水器)、alarm(警报器)、display(显示器),它们来自于不同厂商并进行了组装。那么,应该是heater仅仅负责烧水,它不能发出警报也不能显示水温;在水烧开时由alarm发出警报、display显示水温。

怎么实现“水烧开时,heater通知alarm和display”呢。我们通过“事件”来实现。

范例:
using System;

namespace Delegate {

// 热水器
public class Heater {

private int temperature;
public delegate void BoilHandler(int param); //声明委托
public event BoilHandler BoilEvent; //声明事件

// 烧水
public void BoilWater() {
for (int i = 0; i <= 100; i++) {
temperature = i;
if (temperature > 95) {//水温大于95度时
if (BoilEvent != null) {//如果有对象注册
BoilEvent(temperature); //调用所有注册对象的方法。
}
}
}
}

}


// 警报器
public class Alarm {
public void MakeAlert(int param) {
Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", param);
}
}


// 显示器
public class Display {
public static void ShowMsg(int param) {//静态方法
Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", param);
}
}

class Program {

static void Main() {
Heater heater = new Heater();
Alarm alarm = new Alarm();

heater.BoilEvent += alarm.MakeAlert;//注册方法
heater.BoilEvent += (new Alarm()).MakeAlert; //给匿名对象注册方法
heater.BoilEvent += Display.ShowMsg; //注册静态方法

//烧水,水温大于95度时,会触发事件,自动调用注册过监听该事件的方法。
heater.BoilWater();

}
}
}

但这个范例不符合.net framework规范。符合.net规范的应该是

委托类型的名称都应该以EventHandler结束。委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型(代表了产生该事件的那个对象的引用),一个 EventArgs类型(事件产生时候传递的参数)。

这些不仅仅是为了编码规范,也使得程序有更大的灵活性。比如说,如果我们不光想获得热水器的温度,还想在Observer端 (警报器或者显示器)方法中获得它的生产日期、型号、价格,那么委托和方法的声明都会变得很麻烦,而如果我们将热水器的引用传给警报器的方法,就可以在方法中直接访问热水器了,也就不用在参数e中传递过多的信息了。

 

<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.除了FuncAction,C#中还有哪些常用的委托类型?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、付费专栏及课程。

余额充值