深入理解委托:C# 编程中的强大工具
在面向对象编程中,委托(Delegate) 是一个非常强大且灵活的概念,特别是在 C# 编程语言中。它不仅仅是函数指针的替代品,还提供了更高层次的抽象,使得代码更加简洁、灵活和可维护。在这篇博客中,我们将全面介绍什么是委托、它如何工作、它的主要用途以及如何在 C# 中使用委托。
1. 什么是委托?
委托是 C# 中的一种类型安全的函数指针,它允许您将方法作为参数传递或将方法与事件关联。通过委托,您可以动态地调用不同的方法而不需要在编译时确定具体调用哪个方法。简而言之,委托是一种对象,用于引用方法。
委托的特点
- 类型安全:委托类型与目标方法的签名(返回类型和参数类型)必须一致。
- 封装方法:委托可以封装一个或多个方法,支持多播委托。
- 灵活性:可以将方法作为参数传递或将多个方法与委托关联。
2. 委托的基本语法
在 C# 中,委托的定义和使用非常简单。首先,你需要声明一个委托类型,然后创建一个委托实例并将其指向一个方法,最后可以通过该委托实例调用目标方法。
2.1 定义委托
委托类型的定义使用 delegate
关键字,语法如下:
delegate 返回类型 委托名称(参数列表);
例如,定义一个接受两个整数并返回一个整数的委托类型:
delegate int AddDelegate(int a, int b);
2.2 使用委托
创建委托实例时,您将它与具体的方法关联起来。然后可以通过该委托调用方法。
class Program
{// 定义一个委托类型delegate int AddDelegate(int a, int b);// 定义一个与委托匹配的方法static int Add(int a, int b){return a + b;}static void Main(){// 创建委托实例并将其绑定到 Add 方法AddDelegate addDelegate = new AddDelegate(Add);// 通过委托调用方法int result = addDelegate(5, 3);Console.WriteLine("Result: " + result); // 输出: Result: 8}
}
3. 委托的应用场景
3.1 回调函数
委托可以用于回调函数。回调函数是通过委托传递的方法,它允许将某个方法在程序的后续流程中动态调用。这种方式在异步编程和事件驱动编程中尤其有用。
例如,假设我们有一个方法,它接受一个委托并在完成某个操作后调用该委托:
class Program
{// 定义一个委托类型delegate void Callback(string message);// 任务方法static void DoTask(Callback callback){Console.WriteLine("Task is in progress...");callback("Task completed");}static void Main(){// 通过委托传递回调方法DoTask(Message => Console.WriteLine(Message));}
}
在这个例子中,DoTask
方法接收一个 Callback
委托,允许我们在任务完成后动态调用指定的回调方法。
3.2 事件机制
委托是实现事件的基础。在 C# 中,事件本质上就是委托的封装,它允许对象在发生特定情况时向外界发布通知,而不需要了解接收通知的对象。
例如,定义一个简单的事件系统:
using System;class Program
{// 定义委托类型delegate void Notify(); // 定义事件static event Notify OnCompleted; // 触发事件的方法static void CompleteTask(){Console.WriteLine("Task completed!");OnCompleted?.Invoke(); // 触发事件}static void Main(){// 订阅事件OnCompleted += () => Console.WriteLine("Notified about completion!");// 调用触发事件的方法CompleteTask();}
}
3.3 多播委托
多播委托是指一个委托对象可以包含多个方法。当委托被调用时,它会依次调用其绑定的所有方法。
例如:
using System;class Program
{// 定义委托类型delegate void Notify();// 定义方法static void Task1() { Console.WriteLine("Task 1 completed!"); }static void Task2() { Console.WriteLine("Task 2 completed!"); }static void Main(){// 创建多播委托Notify notify = Task1;notify += Task2; // 添加另一个方法// 调用多播委托notify();}
}
在此示例中,notify
委托绑定了 Task1
和 Task2
方法。当调用 notify()
时,它会依次执行这两个方法。
4. 委托与 Lambda 表达式
在 C# 中,委托通常与 lambda 表达式(匿名方法)一起使用,lambda 表达式提供了更简洁的代码编写方式。
例如,使用 lambda 表达式简化委托的创建和调用:
using System;class Program
{delegate int AddDelegate(int a, int b);static void Main(){// 使用 lambda 表达式创建委托AddDelegate addDelegate = (a, b) => a + b;// 调用委托int result = addDelegate(10, 20);Console.WriteLine($"Result: {result}"); // 输出: Result: 30}
}
这个例子中,lambda 表达式 (a, b) => a + b
替代了传统方法定义,简化了委托的定义过程。
5. 委托的优势与挑战
5.1 委托的优势
- 解耦合:委托使得方法调用者与被调用者解耦,可以动态绑定方法,提升系统的灵活性。
- 事件驱动编程:在事件驱动架构中,委托提供了通知机制,支持事件的发布和订阅。
- 多播功能:委托能够同时调用多个方法,在处理多个订阅者时非常有效。
5.2 委托的挑战
- 性能开销:委托在运行时需要创建额外的对象,这可能会带来一定的性能开销。
- 线程安全:在多线程环境中使用委托时,需要确保线程安全,否则可能会出现竞态条件。
6. 总结
委托是 C# 中非常强大而灵活的功能,它为事件驱动编程、回调函数和多播提供了重要支持。通过委托,我们能够解耦代码,提高灵活性和可维护性。在实际应用中,委托和 lambda 表达式的结合使得代码更加简洁和易于理解。
相关文章:
深入理解委托:C# 编程中的强大工具
在面向对象编程中,委托(Delegate) 是一个非常强大且灵活的概念,特别是在 C# 编程语言中。它不仅仅是函数指针的替代品,还提供了更高层次的抽象,使得代码更加简洁、灵活和可维护。在这篇博客中,我…...

【Java 数据结构】合并两个有序链表
🔥博客主页🔥:【 坊钰_CSDN博客 】 欢迎各位点赞👍评论✍收藏⭐ 目录 1. 题目 2. 解析 3. 代码实现 4. 小结 1. 题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示…...

基于微信小程序的校园访客登记系统
基于微信小程序的校园访客登记系统 功能列表 用户端功能 注册与登录 :支持用户通过手机号短信验证码注册和登录。个人资料管理 :允许用户编辑和更新个人信息及其密码。站内信消息通知:通知公告。来访预约:提交来访预约支持车牌…...

uniapp 判断多选、选中取消选中的逻辑处理
一、效果展示 二、代码 1.父组件: :id=“this.id” : 给子组件传递参数【id】 @callParentMethod=“takeIndexFun” :给子组件传递方法,这样可以在子组件直接调用父组件的方法 <view @click="$refs.member.open()"...
php8.0版本更新了哪些内容
PHP 8.0版本是PHP语言的一个重要更新,它引入了许多新特性和改进,旨在提高性能、增强代码的可读性和可维护性。以下是PHP 8.0版本更新的主要内容: 一、性能提升 JIT编译器:PHP 8.0引入了Just-In-Time(JIT)…...

Browser Use:AI智能体自动化操作浏览器的开源工具
Browser Use:AI智能体自动化操作浏览器的开源工具 Browser Use 简介1. 安装所需依赖2. 生成openai密钥3. 编写代码4. 运行代码5. 部署与优化5.1 部署AI代理5.2 优化与扩展总结Browser Use 简介 browser-use是一个Python库,它能够帮助我们将AI代理与浏览器自动化操作结合起来;…...

Android笔记(四十):ViewPager2嵌套RecyclerView滑动冲突进一步解决
背景 ViewPager2内嵌套横向滑动的RecyclerView,会有滑动冲突的情况,引入官方提供的NestedScrollableHost类可以解决冲突问题,但是有一些瑕疵,滑动横向RecyclerView到顶部,按住它不放手继续往左拖再往右拖,这…...
POS系统即销售点系统 文档与数据库设计
POS系统即销售点系统,是一种用于商业交易的软硬件集成系统,主要用于管理销售、库存、客户信息等,以下是其详细介绍: 1. 系统组成 硬件部分 : 收银终端:包括传统的台式收银机、平板电脑、智能手机等设备&a…...

安全合规遇 AI 强援:深度驱动行业发展新引擎 | 倍孜网络CEO聂子尧出席ICT深度观察报告会!
12月24日,2025中国信通院深度观察报告会科技伦理与合规发展分论坛在北京举办。本次分论坛主题为“伦理先行,合规致远”,聚焦互联网广告合规治理、移动终端应用生态治理、短视频平台责任限度等前沿话题进行分享与探讨。工业和信息化部领导&…...

算法进阶:贪心算法
贪心算法是一种简单而直观的算法思想,它在每一步选择中都采取在当前状态下最优的选择,以期望最终得到全局最优解。贪心算法通常适用于一些具有最优子结构的问题,即问题的最优解可以通过一系列局部最优解的选择得到。 贪心算法的基本思路是&a…...
C++ 设计模式:工厂方法(Factory Method)
链接:C 设计模式 链接:C 设计模式 - 抽象工厂 链接:C 设计模式 - 原型模式 链接:C 设计模式 - 建造者模式 工厂方法(Factory Method)是创建型设计模式之一,它提供了一种创建对象的接口…...
手机联系人 查询 添加操作
Android——添加联系人_android 添加联系人-CSDN博客 上面连接添加联系人已测试 是可以 Android : 获取、添加、手机联系人-ContentResolver简单应用_contentresolver 添加联系人-CSDN博客...

【LeetCode】2506、统计相似字符串对的数目
【LeetCode】2506、统计相似字符串对的数目 文章目录 一、哈希表位运算1.1 哈希表位运算 二、多语言解法 一、哈希表位运算 1.1 哈希表位运算 每个字符串, 可用一个 int 表示. (每个字符 是 int 的一个位) 哈希表记录各 字符组合 出现的次数 步骤: 遇到一个字符串, 得到 ma…...

金仓数据库对象访问权限的管理
基础知识 对象的分类 数据库的表、索引、视图、缺省值、规则、触发器等等,都称为数据库对象,对象分为如下两类: 模式(SCHEMA)对象:可以理解为一个存储目录,包含视图、索引、数据类型、函数和操作符等。非模式对象:其他的数据库对象&#x…...

Qt 中实现系统主题感知
【写在前面】 在现代桌面应用程序开发中,系统主题感知是一项重要的功能,它使得应用程序能够根据用户的系统主题设置(如深色模式或浅色模式)自动调整其外观。 Qt 作为一个跨平台的C图形用户界面应用程序开发框架,提供…...
Modbus TCP 报文说明
Modbus TCP 报文说明 Modbus TCP 报文结构报文解析功能码说明Modbus 功能码与 PLC 地址的对应关系 Modbus TCP 报文结构 事务标识符(Transaction Identifier,2 字节): 用于匹配请求和响应,通常由客户端生成࿰…...

音视频入门基础:MPEG2-TS专题(24)——FFmpeg源码中,显示TS流每个packet的pts、dts的实现
音视频入门基础:MPEG2-TS专题系列文章: 音视频入门基础:MPEG2-TS专题(1)——MPEG2-TS官方文档下载 音视频入门基础:MPEG2-TS专题(2)——使用FFmpeg命令生成ts文件 音视频入门基础…...
大模型:OneFitsAll、Time - LLM、LLaTA
LLM数据集:ETT、Illness、Weather ETT、Illness、Weather在上述提到的论文中都是用于时间序列预测研究的真实世界数据集,以下是对它们的具体介绍: ETT数据集 内容:ETT是电力变压器温度(Electric Transformer Temperature)数据集,通常包含电力变压器在不同时间点的温度…...

连锁餐饮行业数据可视化分析方案
引言 随着连锁餐饮行业的迅速发展,市场竞争日益激烈。企业需要更加精准地把握运营状况、消费者需求和市场趋势,以制定科学合理的决策,提升竞争力和盈利能力。可视化数据分析可以帮助连锁餐饮企业整合多源数据,通过直观、动态的可…...

Ubuntu 下使用命令行将 U 盘格式化为 ext4、FAT32 和 exFAT 的详细教程
Ubuntu 下使用命令行将 U 盘格式化为 ext4、FAT32 和 exFAT 的详细教程 作者:Witheart更新时间:20241228 本教程将详细介绍如何将 U 盘格式化为 ext4、FAT32 和 exFAT 文件系统,同时包括如何安装必要工具(如 exfat-utils&#x…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...