委托
委托#
一、什么是委托#
委托是一种类型安全的函数指针——把”方法”当作变量来传递和存储。
- 本质是一个类,继承自
System.MulticastDelegate,内部维护一个”方法列表” - 类型安全:方法签名(返回值 + 参数类型、个数)必须与委托定义完全一致
- 支持多播:一个委托对象可同时关联多个方法(
+=/-=) - 调用委托时,实际是依次执行内部方法列表
二、使用五步骤(以计算器为例)#
//声明委托:定义函数原型(返回值 + 参数)
public delegate int CalculatorDelegate(int a, int b);
class Program
{
static void Main(string[] args)
{
//实例化委托,关联具体方法
CalculatorDelegate objCal = new CalculatorDelegate(Add);
//通过委托调用方法,而非直接调用
int result = objCal(10, 20); // 实际执行 Add
Console.WriteLine("10+20={0}", result); // 输出 30
//委托关联的方法可动态变化
objCal -= Add; // 断开 Add
objCal += Sub; // 改关联 Sub
result = objCal(10, 20); // 实际执行 Sub
Console.WriteLine("10-20={0}", result); // 输出 -10
}
//按委托原型编写具体方法
static int Add(int a, int b) { return a + b; }
static int Sub(int a, int b) { return a - b; }
}csharp| 步骤 | 内容 | 要点 |
|---|---|---|
| 1 | 声明委托 | 只定义方法”模板”,无功能;一般声明在类外部 |
| 2 | 编写方法 | 签名必须与委托一致(类型安全) |
| 3 | 实例化 | 必须指明默认关联的方法:new CalculatorDelegate(Add),简写 = Add |
| 4 | 调用 | objCal(10,20) 等价于 objCal.Invoke(10,20) |
| 5 | 动态切换 | -= 移除、 += 添加,运行时改变执行的方法 |
三、内置委托(日常首选)#
| 委托 | 签名 | 场景 |
|---|---|---|
Action<T...> | 无返回值,0~16个参数 | 回调通知 |
Func<T..., TResult> | 最后泛型为返回值 | 需要返回结果 |
Predicate<T> | bool(T) | 条件判断 |
例:Func<int,int,int> cal = Add; —— 多数情况不需要自己声明委托类型。
四、核心使用模式:方法当参数(回调)#
static void CalculateAndShow(CalculatorDelegate op, int a, int b)
{
Console.WriteLine($"结果:{op(a, b)}");
}
CalculateAndShow(Add, 10, 20); // 30
CalculateAndShow(Sub, 10, 20); // -10csharp调用方传入不同方法,函数内部代码零修改 —— 这就是”运行时决定行为”的价值。
五、注意事项#
- 调用前判空:
objCal?.Invoke(10, 20) - 多播返回值:多个方法时只保留最后一个的返回值
- 多播异常:链中任一方法抛异常,后续不再执行
- 事件是受限的委托:外部只能
+=/-=,不能=或直接调用 - Lambda 是委托的快捷创建方式,LINQ 的参数本质都是委托(
Func/Predicate)
六、一句话总结#
委托 = 方法的”类型化变量”。声明原型 → 绑定方法 → 调用 → 运行时动态切换;它是事件、Lambda、LINQ 的共同底层基础。