C# 委托(Delegate)详解:从入门到高级用法

在 C# 中,**委托(Delegate)**是一个核心且灵活的特性。它本质上是 类型安全的函数指针 ,允许将方法作为参数传递给其他方法。委托在 事件处理、回调函数、LINQ 查询 等场景中非常常用。

本文将从基础概念、声明与实例化、到多播委托、事件及常用委托类型进行全面讲解,并结合实战示例帮助你快速掌握。


1. 什么是委托?为什么它比函数指针更安全?

委托是一种 引用类型,用于存储对某个方法的引用。它类似于 C/C++ 的函数指针,但比函数指针更安全:

  • 类型安全:只有与委托签名匹配的方法才能赋值给委托。
  • 动态调用:可以在运行时改变委托引用的方法。
  • 广泛应用:事件处理、回调函数、LINQ 查询等。

💡 Tip :所有委托类型都继承自 System.Delegate

场景示例 :在一个算法方法中,根据不同条件动态选择处理方法,委托可以让你轻松传递方法,而无需复杂的 if/else 分支。


2. 如何声明委托?

声明委托的语法如下:

csharp 复制代码
public delegate <返回类型> <委托名>(<参数列表>);

示例:

csharp 复制代码
// 接受两个整数并返回整数
public delegate int MathOperation(int x, int y);

// 接受一个字符串并返回整数
public delegate int MyDelegate(string s);

⚠️ 注意 :委托声明定义了可引用的方法签名,签名不匹配将无法赋值。


3. 实例化与调用委托

创建委托对象通常使用 new 关键字,并绑定具体方法:

csharp 复制代码
public delegate void PrintString(string s);

PrintString ps1 = new PrintString(WriteToScreen);
PrintString ps2 = new PrintString(WriteToFile);

示例:简单委托调用

csharp 复制代码
using System;

delegate int NumberChanger(int n);

class Program
{
    static int num = 10;

    public static int AddNum(int p) => num += p;
    public static int MultNum(int q) => num *= q;
    public static int GetNum() => num;

    static void Main()
    {
        NumberChanger nc1 = new NumberChanger(AddNum);
        NumberChanger nc2 = new NumberChanger(MultNum);

        nc1(25);
        Console.WriteLine("Value of Num: " + GetNum()); // 输出 35

        nc2(5);
        Console.WriteLine("Value of Num: " + GetNum()); // 输出 175
    }
}

🔍 解析

  • nc1 调用 AddNum,累加 25。
  • nc2 调用 MultNum,乘以 5。
  • 委托实现了方法动态调用

4. 多播委托(Multicast Delegate)

多播委托可以让一个委托引用多个方法,通过 + 合并,使用 - 移除:

csharp 复制代码
NumberChanger nc = nc1 + nc2;
nc(5); // 先执行 AddNum,再执行 MultNum
Console.WriteLine("Value of Num: " + GetNum()); // 75

移除方法示例:

csharp 复制代码
PrintMessage print = PrintUpperCase + PrintLowerCase;
print -= PrintLowerCase; // 只剩 PrintUpperCase
print("Hello, C#");       // 输出 HELLO, C#

多播委托执行顺序示意

复制代码
nc = nc1 + nc2
调用 nc(5) ->
    ┌─────────┐
    │ AddNum  │  num += 5
    └─────────┘
    ┌─────────┐
    │ MultNum │  num *= 5
    └─────────┘

💡 Tip:多播委托常用于事件触发,确保所有订阅方法按顺序执行。


5. 委托的常见用途

5.1 回调函数

委托可以作为方法参数,实现"回调机制":

csharp 复制代码
public static void SendString(PrintString ps)
{
    ps("Hello World");
}

5.2 实战:打印字符串到控制台或文件

csharp 复制代码
public delegate void PrintString(string s);

public static void WriteToScreen(string str) => Console.WriteLine(str);
public static void WriteToFile(string s)
{
    using var sw = new StreamWriter("c:\\message.txt", true);
    sw.WriteLine(s);
}

PrintString ps1 = WriteToScreen;
PrintString ps2 = WriteToFile;

SendString(ps1); // 控制台输出
SendString(ps2); // 写入文件

🔍 解析SendString 可以接受任意符合签名的委托,实现逻辑可插拔。


6. 委托与事件

事件是封装了委托的机制,实现发布-订阅模式

csharp 复制代码
public class Button
{
    public event EventHandler Click;

    public void OnClick() => Click?.Invoke(this, EventArgs.Empty);
}

var button = new Button();
button.Click += (s, e) => Console.WriteLine("Button clicked!");
button.OnClick(); // 输出 "Button clicked!"

事件机制示意

复制代码
Button.OnClick() ->
    ┌─────────────┐
    │ Click事件链 │
    └─────────────┘
    ↓
订阅方法逐一执行

💡 Tip:事件只能订阅或取消订阅,不能被外部直接调用,保证封装性。


7. 常用委托类型

委托类型 功能 示例
Action 无返回值 Action<string> print = Console.WriteLine;
Func 有返回值 Func<int,int,int> add = (x,y)=>x+y;
Predicate 返回 bool Predicate<int> isEven = x=>x%2==0;

⚠️ 注意:Action/Func 最多支持 16 个参数,Func 的最后一个参数是返回值。


8. 委托使用注意事项

  1. 类型安全:委托只能引用匹配签名的方法。
  2. 匿名方法 / Lambda:简化实例化。
csharp 复制代码
Func<int,int,int> add = (x,y)=>x+y;
Console.WriteLine(add(5,3)); // 8
  1. 异步调用 :委托可以配合 BeginInvoke / EndInvoke 实现异步操作。

9. 总结与实战建议

C# 委托是一个功能强大、灵活且类型安全的机制。掌握委托可以:

  • 实现 事件驱动编程
  • 实现 回调机制
  • 支持 函数式编程风格
  • 提高程序模块化和代码复用能力

💡 实战建议

  • 事件处理使用多播委托,保证订阅方法顺序执行。
  • 回调函数使用匿名方法或 Lambda 简化代码。
  • 对于复杂场景,可结合 Action/Func/Predicate 提高代码可读性。

📌 本文收获

  • 理解委托概念及类型安全特性
  • 掌握委托的声明、实例化、调用及多播
  • 了解事件与委托的关系
  • 熟悉常用委托类型:Action、Func、Predicate
  • 提高代码复用与模块化能力

💡 文章亮点

  1. 代码示例丰富,每段代码都有解析
  2. 多播委托与事件机制用 ASCII 图示帮助理解
  3. 强调实战场景,贴合开发者使用习惯
  4. 小技巧提示框(Tip/注意)增强可读性
相关推荐
猹叉叉(学习版)2 小时前
【ASP.NET CORE】 7. Identity标识框架
笔记·后端·c#·asp.net·.netcore
喜欢喝果茶.2 小时前
(c#)System.Windows -> SunnyUI
c#
CN.LG3 小时前
SQLiteStudio 介绍
sql·sqlite·c#
leo__5204 小时前
基于C#与HALCON开发的完整视觉检测系统案例
开发语言·c#·视觉检测
唐青枫4 小时前
C#.NET 源生成器 深入解析:编译时代码生成与增量生成器实战
c#·.net
缺点内向4 小时前
.NET办公自动化:Spire.Doc操作Word——文本框移除完整教程
c#·自动化·word·.net
qq_454245039 小时前
增强型ECS(Entity-Component-System)框架
架构·c#
njsgcs12 小时前
solidworks导出展开 c# ExportFlatPatternView方法
c#
格林威12 小时前
工业相机图像高速存储(C#版):内存映射文件方法,附Basler相机C#实战代码!
开发语言·人工智能·数码相机·c#·机器视觉·工业相机·堡盟相机