一、委托的详解
在 C# 中,委托(Delegate)是一个非常重要的概念,它是一种引用类型,用于封装方法,让方法可以像对象一样被传递和调用。委托是回调函数的基础,它为事件驱动编程、异步操作、高阶函数等提供了核心支持。
1. 什么是委托?
委托是一个类似于函数指针的类型,它可以持有对一个方法的引用。
与函数指针不同的是,委托是类型安全的,并且支持多播。
委托的声明
// 声明一个委托类型
public delegate void MyDelegate(string message);
- MyDelegate 是一个委托类型。
- 它表示任何返回类型为 void,参数为一个字符串的方法。
2. 委托的基本使用
示例:委托的声明和使用
using System;
class Program
{
// 声明一个委托
public delegate void PrintDelegate(string message);
static void Main(string[] args)
{
// 创建一个委托实例,指向 Print 方法
PrintDelegate printer = Print;
// 调用委托
printer("Hello, Delegates!");
// 使用匿名方法赋值
printer = delegate (string msg) { Console.WriteLine($"Anonymous: {msg}"); };
printer("Hello from anonymous delegate!");
// 使用 Lambda 表达式赋值
printer = msg => Console.WriteLine($"Lambda: {msg}");
printer("Hello from lambda!");
}
// 与委托签名匹配的方法
static void Print(string message)
{
Console.WriteLine($"Print: {message}");
}
}
【拓展】 printer = msg => Console.WriteLine($“Lambda: {msg}”);
这里的Lambda 表达式是怎么实现的
输出:
Print: Hello, Delegates!
Anonymous: Hello from anonymous delegate!
Lambda: Hello from lambda!
3. 委托的特点
类型安全
委托只能指向与其签名相匹配的方法(参数类型和返回值类型必须一致)。
多播支持
委托可以指向多个方法,调用时会依次执行这些方法。
可组合
使用 += 添加方法,-= 移除方法。
4. 多播委托
示例:多播委托
using System;
class Program
{
public delegate void NotifyDelegate(string message);
static void Main(string[] args)
{
NotifyDelegate notify = Method1;
notify += Method2; // 添加 Method2
notify += Method3; // 添加 Method3
notify("Delegates can multicast!");
notify -= Method2; // 移除 Method2
notify("After removing Method2");
}
static void Method1(string message) => Console.WriteLine($"Method1: {message}");
static void Method2(string message) => Console.WriteLine($"Method2: {message}");
static void Method3(string message) => Console.WriteLine($"Method3: {message}");
}
输出:
Method1: Delegates can multicast!
Method2: Delegates can multicast!
Method3: Delegates can multicast!
Method1: After removing Method2
Method3: After removing Method2
上述多播委托 (Multicast Delegate) 的使用和执行过程解析
1. 代码中的委托定义
public delegate void NotifyDelegate(string message);
- NotifyDelegate 是一个自定义的委托类型。
- 它可以指向任何返回 void 且接收一个 string 参数的方法。
2. 多播委托赋值和组合
NotifyDelegate notify = Method1;
notify += Method2; // 添加 Method2
notify += Method3; // 添加 Method3
- notify 是一个 NotifyDelegate 类型的变量。
- 它最初指向 Method1。
- 使用 += 操作符,将 Method2 和 Method3 添加到多播列表。
最终,notify 包含了三个方法:Method1 -> Method2 -> Method3。
3. 调用多播委托
notify("Delegates can multicast!");
- 当调用 notify 时,所有已订阅的委托方法都会依次执行。
- 输入的参数 message 会被依次传递给 Method1、Method2 和 Method3。
第一次调用的输出:
Method1: Delegates can multicast!
Method2: Delegates can multicast!
Method3: Delegates can multicast!
4. 移除方法
notify -= Method2; // 移除 Method2
notify("After removing Method2");
- 使用 -= 操作符,将 Method2 从 notify 的多播列表中移除。
- 现在,notify 包含的方法是:Method1 -> Method3。
第二次调用的输出:
Method1: After removing Method2
Method3: After removing Method2
5. 执行顺序
在多播委托中:
- 方法按添加的顺序依次执行。
- 如果其中某个方法抛出异常,默认情况下后续方法不会执行。
5. 委托的常用类型
在实际开发中,为了简化委托的使用,C# 提供了几个内置的委托类型:
1.Action
- 无返回值。
- 可接受 0-16 个参数。
完整执行流程总结
1.定义一个多播委托 notify。
2.添加 Method1、Method2 和 Method3 到委托。
3.调用 notify 时,依次执行:
- Method1(“Delegates can multicast!”)
- Method2(“Delegates can multicast!”)
- Method3(“Delegates can multicast!”)
4.使用 -= 移除 Method2。
5.再次调用 notify,只执行 Method1 和 Method3。
优点
- 多播:一个委托变量可以指向多个方法。
- 动态管理:可以随时添加或移除方法。
- 统一调用:只需要调用委托变量,无需单独调用多个方法。
Action<int, string> action = (num, str) => Console.WriteLine($"{num}, {str}");
action(42, "Hello");
2.Func
- 有返回值。
- 最后一个泛型参数为返回类型,其余为输入参数类型。
Func<int, int, string> func = (a, b) => (a + b).ToString();
Console.WriteLine(func(2, 3)); // 输出 "5"
3.Predicate
- 返回 bool 类型。
- 通常用于条件判断。
Predicate<int> isEven = n => n % 2 == 0;
Console.WriteLine(isEven(4)); // 输出 "True"
6. 委托与事件的关系
事件是基于委托实现的。事件可以看作是对委托的进一步封装,用于发布-订阅模式。
事件与委托的区别
- 委托是方法的引用类型,可以直接调用。
- 事件对委托进行了封装,只能在声明类中触发,而不能在外部直接调用。
事件的示例:
using System;
class Program
{
public delegate void NotifyDelegate(string message);
// 声明事件
public event NotifyDelegate NotifyEvent;
static void Main(string[] args)
{
var program = new Program();
// 订阅事件
program.NotifyEvent += msg => Console.WriteLine($"Received: {msg}");
// 触发事件
program.Notify("Hello, Events!");
}
public void Notify(string message)
{
NotifyEvent?.Invoke(message); // 触发事件
}
}
7. 委托的应用场景
回调函数:异步操作的结果处理。
事件机制:用于发布-订阅模型。
策略模式:算法或逻辑的动态选择(如排序比较器)。
高阶函数:动态传递处理逻辑(如 LINQ)。
多播场景:通知多个订阅者(如广播消息)。
总结
委托是 C# 中非常强大的工具,用于封装方法,使其可以动态传递和组合。 委托是事件、回调函数、多播通知等核心机制的基础。 使用内置的
Action、Func、Predicate 类型,可以大幅简化委托的使用。