委托(Delegate)在C#中的概念与应用

什么是委托

委托 是C#中的一种引用类型 ,用于安全地封装方法 ,类似于C/C++中的函数指针,但它是面向对象、类型安全和可靠的。委托本质上是定义方法签名的类型,允许将方法作为参数传递或赋值给变量,实现方法的间接调用。

委托的核心特点

  1. 类型安全:委托确保方法签名匹配,避免了C/C++函数指针可能导致的类型错误
  2. 面向对象委托是.NET Framework中的类,派生自System.Delegate
  3. 引用类型:委托类型是密封的(sealed),不能继承
  4. 封装方法:委托对象可以引用一个或多个方法

委托的语法

声明委托

cs 复制代码
public delegate 返回类型 委托名称(参数列表);
cs 复制代码
// 声明一个委托:可以封装接受字符串参数、返回void的方法
public delegate void Callback(string message);

实例化委托

cs 复制代码
// 定义方法
public static void DelegateMethod(string message) 
{
    Console.WriteLine(message);
}

// 实例化委托
Callback handler = DelegateMethod; // 将方法名赋值给委托

// 使用Lambda表达式实例化
Callback handler2 = (msg) => Console.WriteLine("Lambda: " + msg);

调用委托

cs 复制代码
// 调用委托
handler("Hello World"); // 输出: Hello World
handler2("Hello from Lambda"); // 输出: Hello from Lambda

委托的用途

1. 作为回调方法

委托允许将方法作为参数传递,实现回调机制:

cs 复制代码
public static void MethodWithCallback(int param1, int param2, Callback callback)
{
    callback("The number is: " + (param1 + param2).ToString());
}

// 使用
MethodWithCallback(1, 2, handler); // 输出: The number is: 3

2. 事件处理

事件是委托的特殊应用,用于实现观察者模式:

cs 复制代码
// 定义事件委托
public delegate void ClickEventHandler(object sender, EventArgs e);

// 事件发布者
public class Button
{
    public event ClickEventHandler Clicked;
    
    public void SimulateClick()
    {
        Console.WriteLine("按钮被点击了...");
        Clicked?.Invoke(this, new EventArgs());
    }
}

// 事件订阅者
public class Form
{
    public Form(Button button)
    {
        button.Clicked += Button_Clicked;
    }
    
    private void Button_Clicked(object sender, EventArgs e)
    {
        Console.WriteLine("窗口收到通知:按钮被点击,执行响应逻辑!");
    }
}

3. 多播委托

委托可以链接多个方法,实现多播调用:

cs 复制代码
public class MethodClass
{
    public void Method1(string message) { Console.WriteLine("Method1: " + message); }
    public void Method2(string message) { Console.WriteLine("Method2: " + message); }
}

// 使用多播
var obj = new MethodClass();
Callback d1 = obj.Method1;
Callback d2 = obj.Method2;
Callback d3 = DelegateMethod;

// 链接委托
Callback allMethodsDelegate = d1 + d2;
allMethodsDelegate += d3;

// 调用所有方法
allMethodsDelegate("Hello"); 
// 输出:
// Method1: Hello
// Method2: Hello
// Hello World

C#内置委托

C#提供了常用的泛型委托类型,简化了常见场景的使用:

  • Action:无返回值的委托,支持不同参数数量

    • Action:无参数
    • Action<T>:一个参数
    • Action<T1, T2>:两个参数
    • ...
  • Func:有返回值的委托,支持不同参数数量和返回类型

    • Func<TResult>:无参数,返回TResult
    • Func<T, TResult>:一个参数,返回TResult
    • Func<T1, T2, TResult>:两个参数,返回TResult
    • ...

示例:

cs 复制代码
// 使用Action
Action<string> print = (msg) => Console.WriteLine(msg);
print("Hello");

// 使用Func
Func<int, int, int> add = (a, b) => a + b;
int result = add(3, 5); // 8

委托与事件的关系

事件是基于委托实现的特殊机制,用于实现发布-订阅模式:

  • 事件使用委托类型
  • 事件只能通过+=-=操作符添加或移除方法
  • 事件封装了委托,限制了外部直接调用委托
cs 复制代码
// 事件声明
public event ClickEventHandler Clicked;

// 事件使用
button.Clicked += Form.Button_Clicked; // 订阅
button.Clicked -= Form.Button_Clicked; // 取消订阅

为什么需要委托

  1. 解耦:使组件之间松散耦合,提高代码可维护性
  2. 灵活性:允许在运行时动态决定调用哪个方法
  3. 代码复用:将方法作为参数传递,提高代码复用率
  4. 事件驱动:实现事件处理机制,如UI事件、异步操作完成通知

委托的演变

C#语言对委托功能持续演进:

  • C# 2.0:引入匿名方法
  • C# 3.0:引入Lambda表达式
  • C# 10.0:增强Lambda表达式,允许自然类型推断
  • C# 11.0:改进方法组到委托的转换
  • C# 12.0:为Lambda表达式参数增加可选参数功能

总结

委托是C#中实现动态回调事件驱动 编程的核心机制,它使方法能够像数据一样被传递和使用。通过委托,我们可以编写出更加灵活、可扩展和可维护的代码,是面向对象编程中实现策略模式观察者模式的关键技术。

相关推荐
hunterandroid几秒前
Jetpack Compose 入门:用声明式 UI 写 Android 页面
前端
以和为贵2 分钟前
前端手写 RAG 踩坑实录:四个让检索"翻车"的坑
前端·人工智能·面试
用户2136610035727 分钟前
Redux异步方案与React性能优化Hooks
前端
假如让我当三天老蒯9 分钟前
TypeScript 继续学习(学习用)
前端·面试·typescript
玄玄子9 分钟前
CSS 浮动引起父元素高度塌陷
前端·css
拾年27512 分钟前
我用 30 行代码,搞懂了大模型是怎么"读"中文的
javascript·人工智能·llm
竹林81812 分钟前
从 ethers.js 到 viem:我在一个 DeFi 看板项目中踩过的所有坑与最终方案
前端·javascript
kyrie2814 分钟前
React Redux 完整用法
前端
bonechips20 分钟前
Tool Use:从"缸中大脑"到 AI Agent 的技术真相
javascript·agent
程序员鱼皮20 分钟前
Codex 又出王炸功能「录制回放」,实战测评!附原理浅析
前端·后端·ai编程