delegate是C#中声明匿名方法的唯一语法,必须以delegate关键字开头,可省略参数列表以适配无参委托,但不可省略delegate本身;Lambda表达式与之不同,不具参数灵活性。

delegate 是 C# 中声明和使用匿名方法的唯一语法入口,没有其他“5种方式”——所谓“5种”多是把不同上下文(如事件绑定、线程启动、委托实例化等)误当作独立语法变体。真正有效的用法只有 1 种核心形式,其余全是它在不同场景下的自然延伸。
匿名方法必须用 delegate 关键字声明
匿名方法不是语法糖,也不是可选写法;它必须显式以 delegate 开头,后接可选参数列表和代码块。漏掉 delegate 就不是匿名方法,编译器直接报错:Error CS0149: Method name expected。
-
delegate后面可以**省略参数列表**(即delegate { ... }),此时能适配任意无参委托类型,比如ThreadStart、Action、MethodInvoker - 带参数时必须与目标委托签名兼容,例如
EventHandler要求delegate(object o, EventArgs e) { ... } - 不能省略
delegate关键字去模仿 Lambda,(x) => x.ToString()是 Lambda,不是匿名方法
事件处理中用 delegate 绑定点击逻辑
这是最常见也最容易出错的场景:参数类型不匹配或忘记括号导致编译失败。
- 正确写法:
button.Click += delegate(object sender, EventArgs e) { MessageBox.Show("Clicked!"); }; - 错误写法:
button.Click += delegate { MessageBox.Show("Clicked!"); };—— 缺少参数,无法匹配EventHandler委托签名 - 若想省参,得换委托类型,比如用
button.Click += (s,e) => MessageBox.Show("Clicked!");(Lambda)或先转成Action再调用(不推荐)
启动线程时用 delegate() 省去额外方法
这里 Thread 构造函数接受 ThreadStart(无参委托),所以 delegate 后可直接跟空括号或省略括号。
- 合法:
new Thread(delegate() { Console.WriteLine("Hello"); }) - 也合法:
new Thread(delegate { Console.WriteLine("Hello"); })(省略()) - 但注意:如果线程逻辑里要捕获外部变量(比如
int i = 0;),这个i会延长生命周期,直到委托被 GC —— 容易引发内存泄漏,尤其在线程长期运行时
委托实例化时忽略参数列表是唯一不可替代的用途
Lambda 表达式做不到这点,而某些老 API(尤其是 .NET Framework 2.0–3.5 的控件/库)只接受宽泛签名的委托,这时 delegate 的“参数忽略”能力就不可替代。
- 例如:
delegate void AnyHandler();、delegate void AnyHandler(string s);、delegate void AnyHandler(int a, bool b);都能用同一个delegate { DoSomething(); }赋值 - 而
(a,b) => DoSomething()必须严格匹配参数个数和类型,否则编译不过 - 实际项目中遇到 COM 互操作或老旧 WinForms 插件接口时,这个特性仍可能救急
真正需要警惕的不是“有几种写法”,而是混淆 delegate 匿名方法和 Lambda 的适用边界——后者更简洁通用,前者只剩一个明确的生存理由:参数签名不确定时的兜底适配。写多了容易惯性套用,结果在新项目里留下难以维护的语法化石。


















