每个.NET开发都应掌握的C#委托事件知识点

上篇文章讲述了C#接口的知识点,本文将介绍C#委托事件知识点。C#作为.NET开发的核心语言之一,提供了丰富的特性来支持面向对象编程和事件驱动的模型。其中,委托和事件是C#中不可或缺的关键概念,每个.NET开发者都应该深入理解它们的作用和用法。委托和事件密不可分,所以本文将委托和事件的知识点一起介绍,并通过一些示例来帮助开发者更好地掌握这些重要的概念。

一、委托

委托让方法引用的灵活利用

1、委托的定义与使用

委托是一种数据类型,用于持有对一个或多个方法的引用。通过委托,你可以将方法作为参数传递给其他方法,实现回调机制,实现方法的动态调用。使用`delegate`关键字可以声明委托类型,并创建委托实例来绑定具体方法。

using System;
//定义一个委托
delegate int CalculatorDelegate(int a, int b);
class Calculator
{public int Add(int a, int b){return a + b;}public int Subtract(int a, int b){return a - b;}
}
class Program
{static void Main(string[] args){Calculator calculator = new Calculator();// 声明委托实例,并绑定到 Add 方法CalculatorDelegate funDelegate = new CalculatorDelegate(calculator.Add);// 使用委托调用方法int result = funDelegate (5, 2);Console.WriteLine($"5 + 2 = {result}");// 将委托重新绑定到 Subtract 方法funDelegate = calculator.Subtract;// 使用委托调用不同的方法result = funDelegate(8, 6);Console.WriteLine($"8 - 6 = {result}");}
}

使用try.dot.net的测试结果:

图片

2、委托的多播

委托不仅可以持有单个方法的引用,还可以用于多播,即将多个方法绑定到同一个委托实例。多播委托允许按顺序调用这些方法,实现一次触发多个方法的功能。

using System;
delegate void MyDelegate(); // 定义委托
class EventPublisher
{private MyDelegate eventHandlers; // 多播委托实例public void AddHandler(MyDelegate handler){eventHandlers += handler; // 添加委托方法到多播链}public void RemoveHandler(MyDelegate handler){eventHandlers -= handler; // 从多播链中移除委托方法}public void RaiseEvent(){Console.WriteLine("事件发布者正在引发事件...");eventHandlers?.Invoke(); // 调用多播链中的委托方法}
}
class Program
{static void Main(string[] args){EventPublisher publisher = new EventPublisher();// 添加多个事件处理程序到多播链publisher.AddHandler(Method1);publisher.AddHandler(Method2);publisher.AddHandler(Method3);// 触发事件,调用多播链中的所有方法publisher.RaiseEvent();// 移除一个事件处理程序publisher.RemoveHandler(Method2);// 再次触发事件publisher.RaiseEvent();Console.ReadKey();}static void Method1(){Console.WriteLine("方法1运行.");}static void Method2(){Console.WriteLine("方法2运行.");}static void Method3(){Console.WriteLine("方法3运行.");}
}

输出结果:

图片

3、 匿名方法与Lambda表达式

C# 2.0 引入了匿名方法,允许在没有显示声明方法的情况下传递代码块作为委托参数。而Lambda表达式则是C# 3.0 的新特性,提供了更简洁的语法来创建委托实例。.NET的ORM框架EF中有了Lambda表达式方便多了。

进化:委托–>匿名方法–>Lambda

案例:下面案例是委托匿名方法和Lambda表达式三种使用案例

using System;
using System.Linq;
delegate int MathOperation(int a, int b);
class Calculator
{public int Add(int a, int b){return a + b;}public int Subtract(int a, int b){return a - b;}
}
class Program
{static void Main(string[] args){Calculator calculator = new Calculator();// 1、使用委托和实例方法 AddMathOperation operation1 = calculator.Add;int result1 = operation1(10, 5);Console.WriteLine($"用委托方法计算: 10 + 5 = {result1}");// 2、使用匿名方法进行减法运算//MathOperation  operation2 = delegate (int a, int b)Func<int,int,int> operation2 = delegate (int a, int b)//内置Func{return a - b;};int result2 = operation2(15, 7);Console.WriteLine($"用匿名方法计算: 15 - 7 = {result2}");// 3、使用 Lambda 表达式进行乘法运算//MathOperation operation3 = (a, b) => a * b;//委托变量Func<int,int,int> operation3 = (a, b) => a * b;//内置Funcint result3 = operation3(8, 6);Console.WriteLine($"用Lambda计算: 8 * 6 = {result3}");Console.ReadKey();}
}
//欢迎关注公众号:DOTNET开发跳槽,领取海量面试题。
//加微信号xbhpnet入群交流.NET求职和技术

效果如下:

图片

4、委托的BeginInvoke方法实现异步

委托的 BeginInvoke 方法和 EndInvoke 方法可以实现异步执行委托方法。这允许委托的方法在后台线程中执行,而不会阻塞当前线程。小编在之前的webform开发中遇到下载进度条卡死的问题就是用它解决的。

案例:

using System;
using System.Threading;delegate void PrintDelegate(string message);
class Program
{static void PrintMessage(string message){for (int i = 0; i < 10000; i++){Console.WriteLine(message);}}static void Main(string[] args){PrintDelegate print = PrintMessage;// 使用委托的 BeginInvoke 方法来异步执行方法IAsyncResult result = print.BeginInvoke("执行异步方法!", null, null);// 使用委托的 EndInvoke 方法获取异步操作结果print.EndInvoke(result);//这里不会卡死Console.WriteLine("Begin 后的方法");Console.ReadKey();}
}
//由于控制台不支持展示,大家可以自己研究一下。

二、事件

事件对象之间的松耦合通信

1、事件的定义与声明

事件是委托的一种特殊应用,用于实现发布-订阅模型。使用event关键字可以声明事件,并指定事件委托的类型。事件允许对象通知其他对象在特定情况下执行操作,实现松耦合的通信机制。

 //声名public event TemperatureChangeHandler TemperatureChanged;

2、事件的订阅与发布

订阅事件的类(事件订阅者)可以将其方法绑定到事件上,以便在事件触发时执行操作。事件的持有者(事件发布者)在适当的时机触发事件,调用事件委托,从而通知所有订阅者执行相应的操作。

案例:

using System;// 定义事件发布者类
class EventPublisher
{// 声明事件委托public event EventHandler<string> MessageSent;// 触发事件的方法public void SendMessage(string message){Console.WriteLine($"发送消息:{message}");OnMessageSent(message);}// 触发事件的保护方法protected virtual void OnMessageSent(string message){MessageSent?.Invoke(this, message); // 调用事件}
}// 定义事件订阅者类
class EventSubscriber
{public void Subscribe(EventPublisher publisher){// 订阅事件publisher.MessageSent += HandleMessageSent;}public void Unsubscribe(EventPublisher publisher){// 取消订阅事件publisher.MessageSent -= HandleMessageSent;}// 事件处理方法private void HandleMessageSent(object sender, string message){Console.WriteLine($"接收到消息:{message}");}
}class Program
{static void Main(string[] args){EventPublisher publisher = new EventPublisher();EventSubscriber subscriber1 = new EventSubscriber();EventSubscriber subscriber2 = new EventSubscriber();// 订阅事件subscriber1.Subscribe(publisher);subscriber2.Subscribe(publisher);// 发布事件publisher.SendMessage("你好,订阅者们!");Console.WriteLine("取消一个订阅者的订阅...");// 取消订阅一个订阅者subscriber1.Unsubscribe(publisher);// 发布事件publisher.SendMessage("再次打个招呼!");Console.ReadKey();}
}

输出:

图片

3、事件的安全性与封装

事件提供了一种封装机制,使得事件只能被持有者触发,而不会被外部随意调用。这样可以确保事件只在控制的范围内使用,增强代码的安全性和可维护性。

三、委托与事件的关系

事件是委托的一种特殊用法,用于实现发布者/订阅者模式,实现对象之间的松耦合通信。委托是一种通用的类型,用于引用方法并执行它们,而事件是委托的一种实现,允许对象订阅和响应特定情况的通知,从而促进模块化和可维护的代码设计。通过事件,对象可以在不直接依赖于其他对象的情况下,将重要信息传递给感兴趣的观察者。

下面将用一个案例来理解委托和事件

为了更好地理解委托和事件,我们可以以一个简单的温度监测系统为例。假设有一个温度监测器对象,当温度发生变化时,它可以通知其他对象执行相应的操作。

using System;
// 定义一个委托,用于处理温度变化事件
delegate void TemperatureChangeHandler(double temperature);
// 温度监控类
class TemperatureMonitor
{// 定义事件,将委托作为事件处理程序public event TemperatureChangeHandler TemperatureChanged;private double currentTemperature; // 当前温度// 属性,获取和设置当前温度,当温度发生变化时触发事件public double CurrentTemperature{get { return currentTemperature; }set{if (value != currentTemperature){currentTemperature = value;OnTemperatureChanged(value); // 温度变化时调用事件}}}// 触发温度变化事件的方法protected virtual void OnTemperatureChanged(double temperature){TemperatureChanged?.Invoke(temperature); // 调用事件处理程序}
}
class Program
{static void Main(string[] args){TemperatureMonitor monitor = new TemperatureMonitor();// 订阅温度变化事件,将方法 OnTemperatureChanged 作为事件处理程序monitor.TemperatureChanged += OnTemperatureChanged;// 改变当前温度,触发事件monitor.CurrentTemperature = 25.5;Console.ReadKey();}// 温度变化事件处理程序static void OnTemperatureChanged(double temperature){Console.WriteLine($"温度变化 {temperature}°C");}
}
//案例参考:C#委托事件-张子阳

效果如下:

图片

以上代码示例使用了委托和事件,实现了观察者模式。观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。在这个示例中,TemperatureMonitor 类充当了被观察者(发布者),Program 类中的 OnTemperatureChanged 方法充当观察者(订阅者)

结语

委托和事件是C#中的重要概念,在C#中无论是实现回调机制、处理异步操作,还是实现事件驱动的架构,委托和事件都是不可缺的,每个.NET开发者都应该深入了解和熟练掌握。本文只列出了部分基础知识点,更多知识点大家可以到官网查询。

希望本文对你有所收获,对于C#委托和事件的知识点,你还知道哪些?欢迎留言讨论或者吐槽本文。

参考:

1、chatgpt

2、微软官方文档 :

委托:learn.microsoft.com/zh-cn/dotnet/csharp/programming-guide/delegates/

事件:learn.microsoft.com/zh-cn/dotnet/csharp/programming-guide/events/

来源公众号:DotNet开发跳槽

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/99045.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用字符串匹配算法

一、BF匹配 BF算法中的BF是Brute Force的缩写&#xff0c;中文叫作暴力匹配算法&#xff0c;也叫朴素匹配算法。 BF算法的时间复杂度很高&#xff0c;是O(nm)&#xff0c;但在实际的开发中&#xff0c;它却是一个比较常用的字符串匹配算法。 第一&#xff0c;实际的软件开发中…

JVM——配置常用参数,GC调优策略

文章目录 JVM 配置常用参数Java内存区域常见配置参数概览堆参数回收器参数项目中常用配置常用组合 常用 GC 调优策略GC 调优原则GC 调优目的GC 调优策略 JVM 配置常用参数 Java内存区域常见配置参数概览堆参数&#xff1b;回收器参数&#xff1b;项目中常用配置&#xff1b;常…

【nodejs】用Node.js实现简单的壁纸网站爬虫

1. 简介 在这个博客中&#xff0c;我们将学习如何使用Node.js编写一个简单的爬虫来从壁纸网站获取图片并将其下载到本地。我们将使用Axios和Cheerio库来处理HTTP请求和HTML解析。 2. 设置项目 首先&#xff0c;确保你已经安装了Node.js环境。然后&#xff0c;我们将创建一个…

cuOSD(CUDA On-Screen Display Library)库的学习

目录 前言1. cuOSD1.1 Description1.2 Getting started1.3 For Python Interface1.4 Demo1.5 Performance Table 2. cuOSD案例2.1 环境配置2.2 simple案例2.3 segment案例2.4 segment2案例2.5 polyline案例2.6 comp案例2.7 perf案例 3. cuOSD浅析3.1 simple_draw函数 4. 补充知…

小程序中display:flex和v-show,v-show不生效,uni-app

小程序中display:flex和v-show&#xff0c;v-show不生效、、 解决方案&#xff1a; display&#xff1a;flex样式的优先级高于了v-show &#xff0c;v-show其实就是display&#xff1a;none&#xff0c;display&#xff1a;flex优先级高于display&#xff1a;none。 使用 :s…

【系统工具】开源服务器监控工具WGCLOUD初体验

经常看到服务器上传下载流量一直在跑&#xff0c;也不知道是啥软件在偷偷联网~~~官网地址&#xff1a;www.wgstart.com&#xff0c;个人使用是免费的。 WGCLOUD官网介绍 "WGCLOUD支持主机各种指标监测&#xff08;cpu使用率&#xff0c;cpu温度&#xff0c;内存使用率&am…

了解生成对抗网络 (GAN)

一、介绍 Yann LeCun将其描述为“过去10年来机器学习中最有趣的想法”。当然&#xff0c;来自深度学习领域如此杰出的研究人员的赞美总是对我们谈论的主题的一个很好的广告&#xff01;事实上&#xff0c;生成对抗网络&#xff08;简称GAN&#xff09;自2014年由Ian J. Goodfel…

K8s学习笔记1

一、课程介绍&#xff1a; 1、背景&#xff1a; 1&#xff09;从基础设备主机化向容器化转换。 2&#xff09;从人肉式运维工作模式向自动化运维模式转换。 3&#xff09;从自动化运维体系向全体系智能化运维模式转换。 2、课程目标人群: 1&#xff09;掌握Linux操作系统基…

【数据分享】2006-2021年我国城市级别的节约用水相关指标(免费获取\20多项指标)

《中国城市建设统计年鉴》中细致地统计了我国城市市政公用设施建设与发展情况&#xff0c;在之前的文章中&#xff0c;我们分享过基于2006-2021年《中国城市建设统计年鉴》整理的2006—2021年我国城市级别的市政设施水平相关指标、2006-2021年我国城市级别的各类建设用地面积数…

ES:一次分片设计问题导致的故障

### 现象&#xff1a; 1. 单节点CPU持续高 2.写入骤降 3.线程池队列积压&#xff0c;但没有reject 4.使用方没有记录日志 ### 排查 1.ES监控 只能看到相应的结果指标&#xff0c;无法反应出原因。 2.ES日志&#xff1a;大量日志打印相关异常&#xff08;routate等调用栈&a…

【仿写tomcat】六、解析xml文件配置端口、线程池核心参数

线程池改造 上一篇文章中我们用了Excutors创建了线程&#xff0c;这里我们将它改造成包含所有线程池核心参数的形式。 package com.tomcatServer.http;import java.util.concurrent.*;/*** 线程池跑龙套** author ez4sterben* date 2023/08/05*/ public class ThreadPool {pr…

微服务-Ribbon(负载均衡)

负载均衡的面对多个相同的服务的时候&#xff0c;我们选择一定的策略去选择一个服务进行 负载均衡流程 Ribbon结构组成 负载均衡策略 RoundRobinRule&#xff1a;简单的轮询服务列表来选择服务器AvailabilityFilteringRule 对两种情况服务器进行忽略&#xff1a; 1.在默认情…

Elasticsearch 处理地理信息

1、GeoHash ​ GeoHash是一种地理坐标编码系统&#xff0c;可以将地理位置按照一定的规则转换为字符串&#xff0c;以方便对地理位置信息建立空间索引。首先要明确的是&#xff0c;GeoHash代表的不是一个点而是一个区域。GeoHash具有两个显著的特点&#xff1a;一是通过改变 G…

赴日IT工作 平时接私活开发能去日本搞个IT公司吗?

有小伙伴问&#xff0c;我平时也会接一些私活开发项目&#xff0c;可以直接去日本搞一个IT公司吗&#xff1f;首先给出まとめ&#xff08;总结&#xff09;&#xff0c;如果你没有日本项目经验的话建议先找个会社试试&#xff0c;如果有项目经验的话&#xff0c;那你把前老板的…

PHP入门基础教程 - 专栏导读

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责…

人工智能引领图文扫描新趋势

1. 背景和影响 近日&#xff0c;中国大学生服务外包创新创业大赛决赛在江南大学圆满落幕。为满足现代服务产业企业的现实需求&#xff0c;本次竞赛内容设计充分聚焦企业发展中所面临的技术、管理等现实问题&#xff0c;与产业的结合度更紧密&#xff0c;智能文字识别技术是大赛…

spad芯片学习总结

一、时间相关单光子计数法TCSPC(Time correlated single photon counting) 1> 如果spad接收用单次发射、峰值检测会怎么样 首先spad是概率性触发的器件&#xff0c;探测到的概率远小于1&#xff0c;而且不仅接收信号的光子可以触发&#xff0c;环境光噪声一样会被spad接收到…

Flink 数据集成服务在小红书的降本增效实践

摘要&#xff1a;本文整理自实时引擎研发工程师袁奎&#xff0c;在 Flink Forward Asia 2022 数据集成专场的分享。本篇内容主要分为四个部分&#xff1a; 小红书实时服务降本增效背景Flink 与在离线混部实践实践过程中遇到的问题及解决方案未来展望 点击查看原文视频 & 演…

Selenium的基本使用

文章目录 引入一.选择元素的基本方法1.根据id 选择元素2.根据 class属性选择元素当元素有 多个class类型 时 3.根据 tag名 选择元素4.通过WebElement对象选择元素5.find_element 和 find_elements 的区别 二.等待界面元素出现1.隐式等待2.显示等待 三.操控元素的基本方法1.点击…

基于springboot+vue的武汉旅游网(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…