委托是c#中类型安全的独立引用类型,用于封装方法签名,编译期检查匹配性;通过delegate关键字定义,支持绑定静态/实例方法及lambda,常用action/func等泛型委托。

委托是什么:一个类型安全的函数指针
委托不是语法糖,也不是接口的替代品,它是 C# 中一种独立的引用类型,用来封装方法签名(返回值 + 参数列表)。它允许你把方法当变量传、当参数传、甚至存进集合里。关键点是:编译期就检查签名是否匹配,不匹配直接报错 CS0123。
如何定义委托:用 delegate 关键字声明类型
定义委托就是定义一种“能装哪些方法”的契约。必须显式写出返回类型和参数列表,不能省略 void 或参数名(名字可不同,但类型和顺序必须一致)。
public delegate int CalculatorDelegate(int a, int b); public delegate void LogHandler(string message, DateTime timestamp);
注意:CalculatorDelegate 只能指向返回 int、接受两个 int 参数的方法;LogHandler 只能指向返回 void、接受 string 和 DateTime 的方法。委托名首字母大写,符合 .NET 命名规范。
如何实例化并调用委托:绑定方法 + Invoke() 或直接调用
委托实例可以绑定静态方法、实例方法,甚至 Lambda 表达式。绑定后,调用方式有两种:显式调用 Invoke(),或像调用普通方法一样直接加括号(后者更常用)。
static int Add(int x, int y) => x + y; static int Multiply(int x, int y) => x * y; <p>CalculatorDelegate calc = Add; // 绑定静态方法 int result1 = calc(3, 4); // 直接调用 → 7</p><p>calc = Multiply; // 重新绑定 int result2 = calc.Invoke(3, 4); // 显式调用 → 12</p><p>// 也可绑定 Lambda CalculatorDelegate squareSum = (a, b) => (a + b) * (a + b); int result3 = squareSum(2, 3); // → 25
常见错误:
- 试图绑定签名不匹配的方法,如
calc = Console.WriteLine;→ 编译失败 - 委托变量为
null时直接调用 → 抛出NullReferenceException,建议调用前判空或用空合并运算符calc?.Invoke(1, 2) - 误以为委托实例是“方法本身”,其实它是对象,可赋值、可传递、可为
null
委托的典型用途:事件、回调、策略切换
委托最自然的落脚点不是“自己造一个委托类型”,而是使用框架已定义好的泛型委托,比如 Action、Func、Predicate。它们覆盖了绝大多数场景,避免重复造轮子。
// 不推荐手写
public delegate void NotifyDelegate(string msg);
<p>// 推荐直接用
Action<string> notify = Console.WriteLine;</p><p>// 多参数、带返回值?
Func<int, int, bool> isEvenSum = (x, y) => (x + y) % 2 == 0;</p><p>// 作为参数传入
void ProcessItems(List<int> items, Action<int> handler) {
foreach (var item in items) handler(item);
}
ProcessItems(new List<int> {1, 2, 3}, Console.WriteLine);容易被忽略的一点:委托链(multicast delegate)只对返回 void 的委托有意义。用 += 可组合多个方法,调用时依次执行;但若委托有返回值,只有最后一个方法的结果会被返回,前面的都被丢弃——这点常在自定义事件逻辑中引发隐蔽 bug。









