C#专题之委托
class Program
{
static void Main(string[] args) // 程序入口
{
Message m = new Message(); // 创建Message对象
Action myAction = new Action(m.PrintText); // 将方法绑定到委托
// 这么写也可以,触发委托调用: myAction.Invoke();
myAction(); // 通过委托调用方法
Console.ReadLine(); // 等待用户输入
}
}
class Message
{
public void PrintText() // 无参无返回值方法
{
Console.WriteLine("Hello!"); // 输出文本
}
}
- Action: 专门用于封装无参数且无返回值的方法
- Action myAction = new Action(m.PrintText) 这句
- 将 Message 类的 PrintText 方法绑定到 myAction 委托
- 等效简写:Action myAction = m.PrintText;
- 委托调用: myAction(); // 触发实际绑定的PrintText方法
- 相当于直接调用 m.PrintText()
- 作用:
- 解耦调用:委托将方法调用从
直接调用转为间接调用
- 扩展性基础:此模式是事件处理、回调机制的基础
- 多播委托:可通过
+= 绑定多个方法(此示例为单方法绑定)
多播委托,先看一个声明委托的实例
namespace ConsoleApp1
{
// 1. 声明委托类型,void表示该委托没有返回值,而最后的()表示没有带参数(因为没传参进来)
public delegate void NotificationHandler();
class Program
{
static void Main()
{
// 2. 创建委托实例(此时才需要赋值)
NotificationHandler handler = SomeMethod;
// 3. 调用委托
handler();
}
// 声明静态方法,可以直接调用,无需再创建类实例
static void SomeMethod()
{
Console.WriteLine("方法被调用");
}
}
}
......
namespace ConsoleApp1
{
internal class Program
{
// 声明委托类型
public delegate void NotificationHandler();
static void Main(string[] args)
{
UserService userService = new UserService();
// 这里还有一种比较啰嗦的写法(一样的效果):
// NotificationHandler notifyUsers = new NotificationHandler(userService.SendEmailNotification);
// 开始多播委托
NotificationHandler notifyUsers = userService.SendEmailNotification;
notifyUsers += userService.SendSmsNotification;
notifyUsers += userService.UpdateActivityLog;
notifyUsers += () => Console.WriteLine("【系统】所有通知发送完成!\n");
Console.WriteLine("----- 用户注册成功 -----");
// 执行多播委托
notifyUsers();
Console.WriteLine("\n----- 移除短信通知后 -----");
// 移除其中一个委托
notifyUsers -= userService.SendSmsNotification;
// 再次执行
notifyUsers();
Console.ReadLine();
}
}
// 声明一个业务类
class UserService
{
public void SendEmailNotification()
{
Console.WriteLine("【邮件】已发送欢迎邮件至用户邮箱");
}
public void SendSmsNotification()
{
Console.WriteLine("【短信】已发送欢迎短信至用户手机");
}
public void UpdateActivityLog()
{
Console.WriteLine("【日志】用户注册记录已更新到数据库");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
// delegate 表示匿名函数
Action myAction = delegate() { Console.WriteLine("Hello"); };
// 新的流行写法,使用lam表达式
// Action myAction = ()=> { Console.WriteLine("Hello"); };
myAction();
}
}
}
- 知识点:
delegate关键字在C#中有两个作用
- 声明委托类型: public delegate void NotificationHandler();
- 声明匿名函数(现推荐使用lam表达式): Action myAction = delegate() { Console.WriteLine("Hello"); };
......
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Caculatror caculatror = new Caculatror();
// 直接调用
caculatror.Report();
// 委托调用
Action myAction = new Action(caculatror.Report);
myAction.Invoke();
// 更简便的调用方式
myAction();
// 带参数的委托: Func<T1, T2, TResult>
Func<int, int, int> fun1 = new Func<int, int, int>(caculatror.Add);
Func<int, int, int> fun2 = new Func<int, int, int>(caculatror.sub);
int x = 200;
int y = 100;
Console.WriteLine(fun1.Invoke(x, y));
Console.WriteLine(fun2.Invoke(x, y));
// 更便捷的调用
Console.WriteLine(fun1(x, y));
Console.WriteLine(fun2(x, y));
}
}
class Caculatror
{
public void Report()
{
Console.WriteLine("I have 3 methods.");
}
public int Add(int x, int y) {
return x + y;
}
public int sub(int x, int y)
{
return x - y;
}
}
}