VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • 委托(Delegate):方法的“指针”

委托(Delegate):方法的“指针”

  1. 委托的核心定义与价值
    委托是C#中的引用类型,用于封装方法的签名(参数+返回值)和目标方法,相当于方法的“安全指针”或“回调接口”。其核心价值在于:
    解耦代码:将方法调用与具体实现分离(如事件驱动中的观察者模式);
    动态调用:运行时可切换委托指向的方法;
    支持多播:一个委托实例可指向多个方法,批量执行。
    语法规则:
    用delegate关键字声明委托类型;
    委托的签名必须与目标方vb.net教程C#教程python教程SQL教程access 2010教程法完全匹配;
    委托实例可直接调用,或通过Invoke()/BeginInvoke()异步调用。
  2. 委托的基础用法
    本节通过“计算两个数”的例子,展示委托的声明、实例化、调用流程。
    2.1 完整代码实现
    csharp
	using System;
	
	// 1. 声明委托类型:接受两个int参数,返回int
	delegate int CalculateDelegate(int a, int b);
	
	class Program
	{
	// 目标方法1:加法
	static int Add(int x, int y) => x + y;
	
	// 目标方法2:减法
	static int Subtract(int x, int y) => x - y;
	
	static void Main()
	{
	// 2. 实例化委托:指向Add方法
	CalculateDelegate calc = Add;
	
	// 3. 调用委托:相当于调用Add(5,3)
	int addResult = calc(5,3);
	Console.WriteLine($"加法结果:{addResult}"); // 输出8
	
	// 切换委托指向Subtract方法
	calc = Subtract;
	int subResult = calc(5,3);
	Console.WriteLine($"减法结果:{subResult}"); // 输出2
	
	// 显式调用Invoke方法(与直接调用等价)
	int subResult2 = calc.Invoke(10,4);
	Console.WriteLine($"显式调用结果:{subResult2}"); // 输出6
	}
	}

2.2 逐行代码讲解
委托声明:delegate int CalculateDelegate(int a, int b)
定义一个名为CalculateDelegate的委托类型,要求目标方法必须接受两个int参数并返回int。
目标方法:Add/Subtract
方法签名与委托完全匹配,可被委托封装。
实例化委托:CalculateDelegate calc = Add
将Add方法的引用赋值给委托实例calc,此时calc指向Add。
调用委托:calc(5,3)
直接调用委托,等价于执行Add(5,3);Invoke()是显式调用方式,结果一致。
切换方法:calc = Subtract
委托实例可动态切换指向的方法,体现灵活性。
3. 系统内置委托:简化开发
.NET框架提供了预定义委托类型,无需手动声明,直接使用即可。常用类型如下:
3.1 Action:无返回值的委托
Action系列委托用于封装无返回值的方法,支持0~16个参数。
示例:
csharp

	// Action<int>:接受1个int参数,无返回值
	Action<int> printNumber = num => Console.WriteLine($"数字:{num}");
	printNumber(100); // 输出:数字:100
	
	// Action<string, int>:接受string和int参数,无返回值
	Action<string, int> printUser = (name, age) => Console.WriteLine($"姓名:{name},年龄:{age}");
	printUser("张三",25); // 输出:姓名:张三,年龄:25

3.2 Func:有返回值的委托
Func系列委托用于封装有返回值的方法,支持1~17个参数(最后一个为返回类型)。
示例:
csharp

	// Func<int, int, int>:接受2个int参数,返回int
	Func<int, int, int> multiply = (a,b) => a*b;
	int product = multiply(4,5); // 结果:20
	
	// Func<string, bool>:接受string参数,返回bool
	Func<string, bool> isEmpty = s => string.IsNullOrEmpty(s);
	bool result = isEmpty(""); // 结果:true

3.3 Predicate:返回bool的委托
Predicate是特殊的Func<T, bool>,用于封装判断逻辑的方法(接受1个参数,返回bool)。
示例:
csharp

	// Predicate<string>:判断字符串长度是否大于5
	Predicate<string> isLongString = s => s.Length >5;
	bool isLong = isLongString("HelloWorld"); // 结果:true
  1. 多播委托:批量执行方法
    委托支持多播(Multicast),即一个委托实例可指向多个方法,调用时按添加顺序执行所有方法。
    4.1 完整代码实现
    csharp
	using System;
	
	// 无返回值的委托类型
	delegate void ShowMessageDelegate();
	
	class Program
	{
	static void ShowWelcome() => Console.WriteLine("欢迎光临!");
	static void ShowGoodbye() => Console.WriteLine("再见!");
	static void ShowNotice() => Console.WriteLine("今日活动:全场8折!");
	
	static void Main()
	{
	// 1. 实例化多播委托
	ShowMessageDelegate show = ShowWelcome;
	
	// 2. 添加方法(+=)
	show += ShowGoodbye;
	show += ShowNotice;
	
	// 3. 调用委托:执行所有方法
	Console.WriteLine("=== 第一次调用 ===");
	show();
	
	// 4. 移除方法(-=)
	show -= ShowGoodbye;
	
	Console.WriteLine("
=== 第二次调用 ===");
	show();
	}
	}

4.2 输出结果与讲解
输出:

	=== 第一次调用 ===
	欢迎光临!
	再见!
	今日活动:全场8折!
	
	=== 第二次调用 ===
	欢迎光临!
	今日活动:全场8折!

关键说明:
添加方法:用+=向委托实例添加方法;
移除方法:用-=从委托实例移除方法;
执行顺序:按添加顺序执行所有方法;
返回值问题:若委托有返回值,多播委托仅返回最后一个方法的结果,因此多播委托通常用于无返回值的场景(如Action)。
5. 基础知识拓展
5.1 委托的本质
每个委托类型都是System.Delegate的子类,可通过GetInvocationList()获取所有方法的列表:
csharp

	// 遍历多播委托的所有方法
	foreach (var method in show.GetInvocationList())
	{
	method.DynamicInvoke(); // 动态调用每个方法
	}

5.2 委托与事件的关系
事件是委托的封装,用于限制外部对委托的操作(仅允许订阅+=/取消订阅-=,不能直接调用或赋值)。示例:
csharp

	public class OrderService
	{
	// 声明事件(基于Action委托)
	public event Action OnOrderCompleted;
	
	public void CompleteOrder()
	{
	// 内部触发事件
 	OnOrderCompleted?.Invoke();
	}
	} 	
	// 使用事件
	var service = new OrderService();
	service.OnOrderCompleted += () => Console.WriteLine("订单完成通知:邮件已发送");
	service.CompleteOrder(); // 触发事件

5.3 委托与Lambda表达式
Lambda表达式可简化委托实例化,无需单独定义方法:
csharp

	// 用Lambda代替单独的Add方法
	CalculateDelegate calc = (a,b) => a + b;
	int result = calc(3,4); // 7

5.4 异步委托调用
委托支持异步调用(BeginInvoke/EndInvoke),但现代C#更推荐用Task。示例:
csharp

	// 异步调用委托
	IAsyncResult ar = calc.BeginInvoke(5,3, null, null);
	// 执行其他任务
	// 获取异步结果
	int result = calc.EndInvoke(ar);
  1. 总结
    委托是C#中解耦与动态调用的核心工具:
    核心作用:封装方法,实现代码分离与动态切换;
    常用类型:Action(无返回)、Func(有返回)、Predicate(判断);
    多播委托:批量执行多个方法;
    拓展应用:事件、Lambda表达式、异步调用。
    掌握委托是理解C#事件驱动编程、LINQ、异步编程的基础。
    练习
    实现一个“用户注册通知”系统:
    1.声明委托UserRegisteredDelegate(接受string参数,无返回值);
    2.定义两个方法:SendEmail(打印“发送邮件给xxx”)、SendSms(打印“发送短信给xxx”);
    3.实例化多播委托,添加两个方法,调用委托模拟用户注册后的通知。
    参考代码:
    csharp
	delegate void UserRegisteredDelegate(string username);
	
	static void SendEmail(string name) => Console.WriteLine($"发送邮件给{name}");
	static void SendSms(string name) => Console.WriteLine($"发送短信给{name}");
	
	// 测试
	UserRegisteredDelegate notify = SendEmail;
	notify += SendSms;
	notify("李四");

输出:

	发送邮件给李四 
	发送短信给李四

(本节完)
下一章:事件(Event):委托的封装与应用
(深入讲解事件的本质、观察者模式、事件驱动编程)

本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49374.html


相关教程