C#的委托delegate与事件event
在C#中,delegate(委托)和 event(事件)是两个非常重要的概念,它们主要用于实现回调机制和事件驱动编程。下面详细介绍它们的原理和使用场景。
1. Delegate(委托)
1.1 委托的原理
委托是一种类型,它定义了方法的签名(即方法的参数类型和返回类型)。
委托可以看作是一个函数指针,它允许将方法作为参数传递、存储和调用。
委托是类型安全的,编译器会检查委托和方法签名是否匹配。
委托可以绑定到一个或多个方法(多播委托)。
1.2 委托的声明与使用
声明委托
// 定义一个委托类型,它指向一个没有返回值且接受一个string参数的方法
public delegate void MyDelegate(string message);
使用委托
public class Program
{// 定义一个符合委托签名的方法public static void DisplayMessage(string message){Console.WriteLine("Message: " + message);}public static void Main(string[] args){// 创建委托实例并绑定方法MyDelegate myDelegate = new MyDelegate(DisplayMessage);// 调用委托myDelegate("Hello, Delegate!");}
}
多播委托
委托可以绑定多个方法,调用时会依次执行这些方法。
public class Program
{public static void DisplayMessage1(string message){Console.WriteLine("Message 1: " + message);}public static void DisplayMessage2(string message){Console.WriteLine("Message 2: " + message);}public static void Main(string[] args){MyDelegate myDelegate = DisplayMessage1;myDelegate += DisplayMessage2; // 绑定第二个方法myDelegate("Hello, Multicast Delegate!");}
}
2. Event(事件)
2.1 事件的原理
事件是基于委托的,它是一种特殊的委托,用于实现发布-订阅模式。
事件的主要作用是限制委托的访问权限,确保外部代码只能订阅(+=)或取消订阅(-=)事件,而不能直接调用或覆盖事件。
事件通常用于实现观察者模式,例如 GUI 编程中的按钮点击事件。
2.2 事件的声明与使用
声明事件
// 定义一个委托类型
public delegate void MyEventHandler(object sender, EventArgs e);// 定义一个包含事件的类
public class Button
{// 声明事件public event MyEventHandler Click;// 触发事件的方法public void OnClick(){if (Click != null) // 检查是否有订阅者{Click(this, EventArgs.Empty); // 触发事件}}
}
使用事件
public class Program
{public static void Main(string[] args){Button button = new Button();// 订阅事件button.Click += Button_Click;// 模拟按钮点击button.OnClick();}// 事件处理方法private static void Button_Click(object sender, EventArgs e){Console.WriteLine("Button clicked!");}
}
3. 委托与事件的区别
特性 委托 (Delegate) 事件 (Event)
访问权限 可以从外部直接调用或覆盖 只能从声明它的类内部触发
多播支持 支持多播(绑定多个方法) 支持多播(绑定多个事件处理方法)
用途 通用回调机制,方法传递 实现发布-订阅模式,事件驱动编程
安全性 较低,外部代码可以随意修改委托 较高,外部代码只能订阅或取消订阅事件
4. 使用场景
4.1 委托的使用场景
回调机制:将方法作为参数传递给其他方法,例如异步编程中的回调。
多播委托:需要依次调用多个方法的场景,例如日志记录系统。
动态方法调用:在运行时决定调用哪个方法。
示例:异步编程中的回调
public delegate void AsyncCallback(int result);public class Calculator
{public void AddAsync(int a, int b, AsyncCallback callback){Task.Run(() =>{int result = a + b;callback(result); // 异步完成后调用回调});}
}public class Program
{public static void Main(string[] args){Calculator calculator = new Calculator();calculator.AddAsync(10, 20, result => Console.WriteLine("Result: " + result));}
}
4.2 事件的使用场景
GUI 编程:例如按钮点击、鼠标移动等事件。
发布-订阅模式:例如消息队列、通知系统。
解耦:将事件的触发者和处理者解耦,提高代码的可维护性。
示例:GUI 中的按钮点击事件
public class Button
{public event EventHandler Click;public void OnClick(){Click?.Invoke(this, EventArgs.Empty);}
}public class Program
{public static void Main(string[] args){Button button = new Button();button.Click += (sender, e) => Console.WriteLine("Button clicked!");button.OnClick();}
}
5. 总结
委托:用于定义方法签名,支持多播,适合实现回调机制。
事件:基于委托,用于实现发布-订阅模式,适合解耦和事件驱动编程。
在实际开发中,事件是委托的一种高级应用,通常用于需要更高安全性和解耦的场景。
相关文章:
C#的委托delegate与事件event
在C#中,delegate(委托)和 event(事件)是两个非常重要的概念,它们主要用于实现回调机制和事件驱动编程。下面详细介绍它们的原理和使用场景。 1. Delegate(委托) 1.1 委托的原理 委托…...
apache artemis安装
安装apache artemis https://xxzkid.github.io/2025/apache-artemis-install...

Lightning基础训练尝试实例
一、训练任务概述 动机:由于后续的课题中会用到类似图像去噪的算法,考虑先用U-Net,这里做一个前置的尝试。 训练任务:分割出图像中的细胞。 数据集:可私 数据集结构: 二、具体实现 U-Net的网络实现是现…...
osgearth视点坐标及鼠标交点坐标的信息显示(七)
核心函数如下: void COSGObject::addViewPointLabel() {//mRoot->addChild(osgEarth::Util::Controls::ControlCanvas::get(mViewer));//放开这句,球就卡住了。 为什么,shitosgEarth::Util::Controls::ControlCanvas* canvas = osgEarth::Util::Controls::ControlCanvas…...

动态规划 之 背包问题
文章目录 0-1背包问题2915.和为目标值的最长子序列的长度494.目标和 完全背包问题322.零钱兑换518.零钱兑换II 多重背包2585.获得分数的方法数 分组背包1155.掷骰子等于目标和的方法数 背包问题是动态规划一个很重要的一类题目,主要分为0-1背包问题以及完全背包问题…...

【Azure 架构师学习笔记】- Azure Databricks (11) -- UC搭建
本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (10) – UC 使用 前言 由于ADB 的更新速度很快,在几个月之后重新搭建ADB 时发现UC 已经更新了很多,为了后续做ADB 的功…...
RTMP(Real-Time Messaging Protocol)
RTMP(Real-Time Messaging Protocol)是一种用于实时音视频和数据传输的协议,常见于直播和流媒体应用。 一 RTSP 协商消息 一、消息类型(Message Types) RTMP消息分为多种类型,通过Message Type ID标识&a…...

docker容器部署jar应用导入文件时候报缺少字体错误解决
如题,在导入文件时候报错如下: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager 经查是缺少对应字体,解决办法有两张: 第一种:…...

贪吃蛇解析
目录 文章结尾有代码可自取 Win32API 光标的隐藏 获取按键信息 控制光标位置 游戏开始前的准备 游戏准备及介绍 加载和欢迎界面 打印游戏指南 运行游戏 打印墙体和说明 设置蛇的各个信息 初始化及打印蛇 创造食物 运行游戏 1)打印得分情况 2&#…...

vue非组件的初学笔记
1.创建Vue实例,初始化渲染的核心 准备容器引包创建Vue实例new Vue() el用来指定控制的盒子data提供数据 2.插值表达式 作用利用表达式插值,将数据渲染到页面中 格式{{表达式}} 注意点 表达式的数据要在data中存在表达式是可计算结果的语句插值表达式…...

LeetCode 热题 100_单词搜索(60_79_中等_C++)(深度优先搜索(回溯))(初始化二维vector的大小)
LeetCode 热题 100_单词搜索(60_79) 题目描述:输入输出样例:题解:解题思路:思路一(深度优先搜索(回溯)): 代码实现代码实现(思路一&am…...
js闭包,跨域
js闭包,跨域 闭包 想象一下,你家有个大仓库(函数),仓库里放着各种东西(变量)。一般情况下,你从仓库外面是看不到也拿不到仓库里的东西的。但是,闭包就像是你在仓库里留…...
算法练习(力扣-BFS)——102. 二叉树的层序遍历
题目描述(简要概括) 题目链接:102. 二叉树的层序遍历 - 力扣(LeetCode) 题目要求对给定的二叉树进行层序遍历(从上到下,从左到右),并返回遍历的结果。层序遍历是一种基…...

Jetson Agx Orin平台preferred_stride调试记录--1924x720图像异常
1.问题描述 硬件: AGX Orin 在Jetpack 5.0.1和Jetpack 5.0.2上测试验证 图像分辨率在1920x720和1024x1920下图像采集正常 但是当采集图像分辨率为1924x720视频时,图像输出异常 像素格式:yuv_uyvy16 gstreamer命令如下 gst-launch-1.0 v4l2src device=/dev/video0 ! …...

nlp|微调大语言模型初探索(2),训练自己的聊天机器人
前言 上篇文章记录了具体的微调语言大模型步骤,以及在微调过程中可能遇见的各种报错,美中不足的是只是基于开源数据集的微调,今天来记录一下怎么基于自己的数据集去微调大语言模型,训练自己的智能机器人!!&…...

win11安装wsl报错:无法解析服务器的名称或地址(启用wsl2)
1. 启用wsl报错如下 # 查看可安装的 wsl --install wsl --list --online此原因是因为没有开启DNS的原因,所以需要我们手动开启DNS。 2. 按照如下配置即可 Google的DNS(8.8.8.8和8.8.4.4) 全国通用DNS地址 (114.114.114.114) 3. 运行以下命令来重启 WSL…...
Gentleman:优雅的Go语言HTTP客户端工具包
gentlemen介绍,特点等 插件驱动架构:Gentleman的核心特点是其插件系统,允许用户注册和重用各种自定义插件,如重试策略或动态服务器发现,以增强HTTP客户端的功能。 中间件层:项目内置了一个上下文感知的层次…...

解锁豆瓣高清海报(三)从深度爬虫到URL构造,实现极速下载
脚本地址: 项目地址: Gazer PosterBandit_v2.py 前瞻 之前的 PosterBandit.py 是按照深度爬虫的思路一步步进入海报界面来爬取, 是个值得学习的思路, 但缺点是它爬取慢, 仍然容易碰到豆瓣的 418 错误, 本文也会指出彻底解决旧版 418 错误的方法并提高爬取速度. 现在我将介绍…...

IDEA单元测试插件 SquareTest 延长试用期权限
SquareTest是一款强大的IDEA单元测试生成插件工具,具体使用方法就不过多介绍了,这里主要介绍变更试用期,方便大家使用 配置信息 我的电脑安装前提配置条件 IntelliJ IDEA 2023.2windows 系统 软件安装 IntelliJ IDEA 直接安装插件Squar…...
PLC的五个学习步骤
五个学习步骤详解: 1. 夯实电气基础 (第一步) 核心思想: PLC控制技术是建立在传统电气控制技术之上的,因此扎实的电气基础至关重要。学习内容: 电气元件原理: 深入理解继电器、接触器、按钮、三相异步电机等常用电气元件的工作原理。这是理解电气控制回…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...