C#中委托和事件的使用总结
委托(delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。事件是一种特殊的多播委托,仅可以从声明事件的类或结构中对其进行调用。类或对象可以通过事件向其他类或对象通知发生的相关事情。本文主要介绍C#中委托和事件的使用总结。
1、委托的简单使用
一个委托类型定义了该类型的实例能调用的一类方法,这些方法含有同样的返回类型和同样参数(类型和个数相同)。委托和接口一样,可以定义在类的外部。
例如,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{delegate int Calculator(int x);class Program{static int Double(int x) { return x * 2; }static void Main(string[] args){Calculator c = Double;int result = c(2);Console.Write(result);Console.ReadKey();}}
}
2、用委托实现插件式编程
委托是一个能把方法作为参数传递的对象,通过这个可以来实现插件式编程。
例如,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{delegate int Calculator(int x);class Program{static int Double(int x) { return x * 2; }static void Main(string[] args){int[] values = { 1, 2, 3, 4 };Utility.Calculate(values, Double);//使用方法Utility.Calculate(values, x => x * 2);//使用Lambda表达式foreach (int i in values)Console.Write(i + " "); // 2 4 6 8Console.ReadKey();}}class Utility{public static void Calculate(int[] values, Calculator c){for (int i = 0; i < values.Length; i++)values[i] = c(values[i]);}}
}
3、多播委托
多播委托是指在一个委托中注册多个方法,在注册方法时可以在委托中使用加号运算符或者减号运算符来实现添加或撤销方法。创建一个委托被调用时要调用的方法的调用列表。这被称为委托的 多播(multicasting),也叫组播。
例如,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{public delegate void ProgressReporter(int percentComplete);public class Utility{public static void Match(ProgressReporter p){if (p != null){for (int i = 0; i <= 10; i++){p(i * 10);System.Threading.Thread.Sleep(100);}}}}class Program{static void Main(string[] args){ProgressReporter p = WriteProgressToConsole;p += WriteProgressToFile;Utility.Match(p);Console.WriteLine("Done.");Console.ReadKey();}static void WriteProgressToConsole(int percentComplete){Console.WriteLine(percentComplete + "%");}static void WriteProgressToFile(int percentComplete){System.IO.File.AppendAllText("progress.txt", percentComplete + "%");}}
}
4、静态方法和实例方法对于委托的区别
一个类的实例的方法被赋给一个委托对象时,在上下文中不仅要维护这个方法,还要维护这个方法所在的实例。System.Delegate 类的Target属性指向的就是这个实例。
例如,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace BRG
{public delegate void ProgressReporter(int percentComplete);class Program{static void Main(string[] args){X x = new X();ProgressReporter p = x.InstanceProgress;p(1);Console.WriteLine(p.Target == x); // TrueConsole.WriteLine(p.Method); // Void InstanceProgress(Int32) }static void WriteProgressToConsole(int percentComplete){Console.WriteLine(percentComplete + "%");}static void WriteProgressToFile(int percentComplete){System.IO.File.AppendAllText("progress.txt", percentComplete + "%");}}class X{public void InstanceProgress(int percentComplete){// do something }}
}
但对于静态方法,System.Delegate 类的Target属性是Null,所以将静态方法赋值给委托时性能更好。
5、泛型委托
泛型委托和泛型的用法一样,就是含有泛型参数的委托。
例如,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{public delegate T Calculator<T>(T arg);class Program{static int Double(int x) { return x * 2; }static void Main(string[] args){int[] values = { 1, 2, 3, 4 };Utility.Calculate(values, Double);foreach (int i in values)Console.Write(i + " "); // 2 4 6 8Console.ReadKey();}}class Utility{public static void Calculate<T>(T[] values, Calculator<T> c){for (int i = 0; i < values.Length; i++)values[i] = c(values[i]);}}
}
6、事件的基本使用
声明一个事件很简单,只需在声明一个委托对象时加上event关键字就行。
例如,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Example_EventTest
{class Judgment{//定义一个委托public delegate void delegateRun();//定义一个事件public event delegateRun eventRun;//引发事件的方法public void Begin(){eventRun();//被引发的事件}}class RunSports{//定义事件处理方法public void Run(){Console.WriteLine("开始运行方法");}}class Program{static void Main(string[] args){RunSports runsport = new RunSports();//实例化事件发布者Judgment judgment = new Judgment();//实例化事件订阅者//订阅事件judgment.eventRun+=new Judgment.delegateRun(runsport.Run);//引发事件judgment.Begin();Console.ReadKey();}}
}
注意:事件有一系列规则和约束用以保证程序的安全可控,事件只有 += 和 -= 操作,这样订阅者只能有订阅或取消订阅操作,没有权限执行其它操作。如果是委托,那么订阅者就可以使用 = 来对委托对象重新赋值(其它订阅者全部被取消订阅),甚至将其设置为null,甚至订阅者还可以直接调用委托。
事件保证了程序的安全性和健壮性。
7、事件的标准模式
.NET 框架为事件编程定义了一个标准模式。设定这个标准是为了让.NET框架和用户代码保持一致。System.EventArgs是标准模式的核心,它是一个没有任何成员,用于传递事件参数的基类。按照标准模式,事件定义委托,必须满足以下条件:
1)必须是 void 返回类型;
2)必须有两个参数,且第一个是object类型,第二个是EventArgs类型(的子类);
3)它的名称必须以EventHandler结尾。
例如,
using System;
namespace ConsoleApplication1
{class Program{static void Main(string[] args){Counter c = new Counter(new Random().Next(10));c.ThresholdReached += c_ThresholdReached;Console.WriteLine("press 'a' key to increase total");Console.WriteLine("adding one");c.Add(1);while (Console.ReadKey(true).KeyChar == 'a'){Console.WriteLine("adding one");c.Add(1);}}static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e){Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached);Environment.Exit(0);}}class Counter{private int threshold;private int total;public Counter(int passedThreshold){threshold = passedThreshold;}public void Add(int x){total += x;if (total >= threshold){ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();args.Threshold = threshold;args.TimeReached = DateTime.Now;OnThresholdReached(args);}}protected virtual void OnThresholdReached(ThresholdReachedEventArgs e){EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;if (handler != null){handler(this, e);}}public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;}public class ThresholdReachedEventArgs : EventArgs{public int Threshold { get; set; }public DateTime TimeReached { get; set; }}
}
相关文章:
C#中委托和事件的使用总结
委托(delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。事件是一种特殊的多播委托,仅可以从声明事件的类或结构中对其进行调用。类或对象可以通过事件向其他类或对象通知发生的…...
基于STM32的外部中断(EXTI)在嵌入式系统中的应用
外部中断(External Interrupt,EXTI)是STM32嵌入式系统中常见且重要的功能之一。它允许外部事件(例如按键按下、传感器触发等)通过适当的引脚触发中断,从而应用于各种嵌入式系统中。在STM32微控制器中&#…...
【心得】PHP的文件上传个人笔记
目录 1 php的文件上传绕过 黑名单绕过 2 php文件上传的00截断 3 iconv字符转换异常后造成了字符截断 4 文件后缀是白名单的时候的绕过 web服务器的解析漏洞绕过 5.高级文件上传绕过 1 .htaccess nginx.htaccess 2 服务端内容检测 3 配合伪协议来绕过 4.配合日志包含绕…...
深度学习之基于Pytorch和OCR的识别文本检测系统
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介深度学习与OCRPyTorch在OCR中的应用文本检测系统的关键组成部分1. 图像预处理2. 深度学习模型3. 文本检测算法4. 后处理 二、功能三、系统四. 总结 一项目简…...
三十一、W5100S/W5500+RP2040树莓派Pico<TCP_Server多路socket>
文章目录 1 前言2 简介2. 1 使用多路socket的优点2.2 多路socket数据交互原理2.3 多路socket应用场景 3 WIZnet以太网芯片4 多路socket设置示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 W5100S/W5500是一…...
带你精通chrony服务器
华子目录 为什么会出现Chrony?Linux的两个时钟NTP介绍Chrony介绍安装与配置安装Chrony配置文件分析实验1实验2chronyc命令查看时间服务器chronyc sources输出分析其他命令 常见时区 为什么会出现Chrony? 由于IT系统中,准确的计时非常重要&am…...
vs2017 编译Qt 5.11.2 源码
SDK 10.0.22000.194 有 2种编译方式 ,第二种 看下面 方式一: 1、问题描述: 使用VS编译程序时,运行库选择多线程(/MT),表示采用多线程静态release的方式进行编译。 但是,发现编译是不能通过的…...
【SpringBoot3+Vue3】四【实战篇】-前端(vue基础)
目录 一、项目前置知识 二、使用vscode创建 三、vue介绍 四、局部使用vue 1、快速入门 1.1 需求 1.2 准备工作 1.3 操作 1.3.1 创建html 1.3.2 创建初始html代码 1.3.3 参照官网import vue 1.3.4 创建vue应用实例 1.3.5 准备div 1.3.6 准备用户数据 1.3.7 通过…...
element ui修改select选择框背景色和边框色
一、修改选择框的背景色和边框色 style部分 .custom-select /deep/ .el-input__inner {color: #fff!important;border: 1px solid #326AFF;background: #04308D !important; } html部分 <el-select class"custom-select" v-model"dhvalue" placeholde…...
软件测试人员提问常用的ChatGPT通用提示词模板
如何设计有效的软件测试用例? 如何运用自动化测试工具进行软件测试? 如何进行软件的功能测试、性能测试和安全测试? 如何评估软件测试的质量和覆盖范围? 软件测试有哪些常见的缺陷和错误,如何识别和解决࿱…...
【开源】基于JAVA的服装店库存管理系统
项目编号: S 052 ,文末获取源码。 \color{red}{项目编号:S052,文末获取源码。} 项目编号:S052,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 服…...
Jenkins代码检测和本地静态检查
1:Jenkins简介 Jenkins是一个用Java编写的开源的持续集成工具;Jenkins自动化部署可以解决集成、测试、部署等重复性的工作,工具集成的效率明显高于人工操作;并且持续集成可以更早的获取代码变更的信息,从而更早的进入测…...
从0开始学习JavaScript--JavaScript 字符串与文本内容使用
JavaScript中的字符串和文本内容处理是前端开发中的核心技能之一。本文将深入研究字符串的创建、操作,以及文本内容的获取、修改等操作,并通过丰富的示例代码,帮助读者更全面地了解和应用这些概念。 JavaScript 字符串基础 字符串是JavaScr…...
Linux--网络概念
1.什么是网络 1.1 如何看待计算机 我们知道,对于计算机来说,计算机是遵循冯诺依曼体系结构的(即把数据从外设移动到内存,再从内存到CPU进行计算,然后返回内存,重新读写到外设中)。这是一台计算机…...
C# 中的 Math 数学函数
C# 中的 Math 类提供了许多数学函数,用于执行各种常见的数学运算。以下是 Math 类中的一些常用方法: Math 数学函数 Abs: 返回指定数字的绝对值Acos: 返回指定数字的反余弦值(弧度)Asin: 返回指定数字的反正弦值(弧度&…...
mybatis之主键返回
1.在mybatis的xml中加入 <insert id"insertUser" keyProperty"id" useGeneratedKeys"true" parameterType"com.UserAndOrder"> insert into Tuser(userName,passWord) values (#{userName},#{passWord} ) </insert&…...
ChatGpt3.5已经应用了一段时间,分享一些自己的使用心得.
首先ChatGpt3.5的文本生成功能十分强大,但是chatgpt有一些使用规范大家需要注意,既然chat是一种工具,我们就需要学会它的使用说明,学会chatgpt的引用语句,会极大的方便我们的使用。我们需要做以下的准备。 明确任务和目…...
有趣的按钮分享
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 广告打完,我们进入正题,先看效果: 废话不多,上源码: <button class&quo…...
论文阅读:YOLOV: Making Still Image Object Detectors Great at Video Object Detection
发表时间:2023年3月5日 论文地址:https://arxiv.org/abs/2208.09686 项目地址:https://github.com/YuHengsss/YOLOV 视频物体检测(VID)具有挑战性,因为物体外观的高度变化以及一些帧的不同恶化。有利的信息…...
如何将图片转为excel或word?(客户端)
演示软件:金鸣表格文字识别大师3.6.1(新版本界面可能会略有不同) 第一部分 将图片转为excel或文表混合的word 一般的软件要将图片转为可编辑的excel,都需要待识别的图片要有明显清晰的表格线,但我们程序现已克服了这…...
华为、华三、思科、锐捷网络设备远程登录配置
目录 一、华为Stelnet登录配置 二、华三Stelent登录配置 三、思科SSH登录配置 四、锐捷SSH登录配置 一、华为Stelnet登录配置 #查看SSH状态# [Server]dis ssh server status SSH Version : 2.0 SSH authentication timeout (Seconds) : 60 SSH authentication retries …...
【从零学Vibe Coding】第一章:Vibe Coding 到底是什么?
第一章:Vibe Coding 到底是什么? 先说结论 Vibe Coding 不是"不写代码",而是"先用自然语言描述意图,再让 AI 生成代码,人类负责判断、修正和推进结果"。 这个词在 2025 年突然出圈,不…...
百度 Agent 安全中心:构筑企业智能体的安全底座
本文整理自 2026 年 5 月 14 日 Create2026 百度 AI 开发者大会 - Agent Infra 专题论坛,百度智能云云安全产品总经理聂科峰的同名主题演讲。在 AI 生产力加速进化的时代,Agent 正在从「会说」快速演进到「会做」。从 Chatbot、Copilot,到能够…...
良心云服务器部署的AI应用如何借助Taotoken实现多模型降级策略
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 良心云服务器部署的AI应用如何借助Taotoken实现多模型降级策略 在生产环境中,部署于云服务器上的AI应用对服务的连续性…...
别再死磕原生OpenStack了!华为云Stack HCS 8.0的极简部署与高可用设计,真香!
华为云Stack HCS 8.0:企业私有云部署的革命性突破 当企业IT架构师面对私有云平台选型时,部署复杂性和系统可靠性往往成为最令人头疼的两大难题。原生OpenStack以其高度灵活性和开源特性吸引了大量技术团队,但随之而来的却是漫长的部署周期、繁…...
单词拆分----dp
思路:刚开始看的时候没有思路,但我看给的样例,可以多次遍历wordDict看。。。好像不太对准备看看题解。首先需要知道这道题的dp的公式代表这什么,dp[i]表示 字符串s从起始位置到位置i,能否被被拆分成字典中的单词&#…...
Datasheet学习4(Audio)(TODO)
(TODO)...
ESP8266 AT指令连接阿里云物联网平台,我踩过的那些坑(附client_id转义完整解决方案)
ESP8266 AT指令连接阿里云物联网平台的实战避坑指南 当ESP8266遇上阿里云物联网平台,本该是物联网开发的黄金组合,却总在AT指令的细节处暗藏杀机。记得第一次用ATMQTTUSERCFG配置客户端时,那个带着逗号的client_id让我在深夜的实验室里对着串…...
2026年京东云OpenClaw/Hermes Agent配置Token Plan集成详细攻略
2026年京东云OpenClaw/Hermes Agent配置Token Plan集成详细攻略。OpenClaw是开源的个人AI助手,Hermes Agent则是一个能自我进化的AI智能体框架。阿里云提供计算巢、轻量服务器及无影云电脑三种部署OpenClaw 与 Hermes Agent的方案、百炼Token Plan兼容主流 AI 工具&…...
MSP430F5438 RTC模块配置与低功耗应用实战指南
1. 项目概述与核心价值最近在整理一个老项目的资料,翻到了当年用TI的MSP430F5438做的一个数据记录仪。这个项目里,实时时钟(RTC)模块的稳定性和低功耗配置是关键,当时为了搞定它,可没少花功夫。今天就把关于…...
