C#_事件简述

事件模型简述

C#中事件的运行模式为"发布订阅模型",事件触发者称为"发布者",事件处理者称为"订阅者"

事件模型的五个组成部分

  1. 事件(成员)
  2. 事件的拥有者(类/对象)
  3. 事件的响应者(类/对象)
  4. 事件处理器(事件处理器的成员方法)
  5. 事件订阅(+= -=)

五个组成部分的关系为:

事件的拥有者拥有事件事件的响应者订阅事件。当事件被触发后,事件的拥有者事件通知事件的响应者事件的响应者通过事件处理器处理事件

事件示例:System.Timers.Timer

System.Timers.Timer是.NET提供的线程不安全的计时器类,此处介绍其Elapsed事件

System.Timers.Timer timer = new(1000);
// Elapsed事件 通过"+="订阅事件
timer.Elapsed += (sender, e) =>
{Console.WriteLine("System.Timers.Timer");
};
timer.Start();
Thread.Sleep(6000);
// 停止计时器
timer.Dispose();

间隔1S事件就会被触发一次,然后被事件处理器处理

事件的完整声明

private static void Main(string[] args)
{Customer customer = new();Waiter waiter = new();customer.Order += waiter.TakeOrder;customer.Think("Cake", "Medium");
}public class Customer
{private OrderEventHandler orderEventHandler; // 事件用于接收订阅的委托public event OrderEventHandler Order         // 事件{add{orderEventHandler += value;}remove{orderEventHandler -= value;}}public double Bill { get; set; }public void Think(string dishName, string size){Console.WriteLine("Customer: I need {0} {1}", size, dishName);OnOrder("Cake", "Medium");}protected void OnOrder(string dishName, string size){if (orderEventHandler != null){OrderEventArgs args = new();args.DishName = dishName;args.Size = size;orderEventHandler(this, args);}}
}
public class Waiter
{public void TakeOrder(Customer customer, OrderEventArgs e){Console.WriteLine("I will serve you the dish - {0} {1}", e.Size, e.DishName);double basePrice = 10;switch (e.Size){case "small":basePrice *= 0.5;break;case "large":basePrice *= 1.5;break;default:break;}customer.Bill += basePrice;Console.WriteLine("You need to pay ${0}", customer.Bill);}
}
// 依据.net规范, 类的作用是传递事件信息(EventArgs)时, 需在声明时添加EventArgs后缀, 并实现EventArgs类
public class OrderEventArgs : EventArgs
{public string DishName { get; set; }public string Size { get; set; }
}
// 依据.net规范, 委托的作用是处理事件时, 需要在声明时添加EventHandler后缀
public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);

上述代码中,事件的五个组成部分:customer是事件的拥有者,waiter是事件的响应者,customer.Order是事件,waiter.TakeOrder是事件处理器,"+="是事件的订阅。此外,orderEventHandler是事件用于接收订阅的委托,customer.Think是事件的触发者

需要说明的是:

1.依据.net规范,类的作用是传递事件信息(EventArgs)时,需在声明时添加EventArgs后缀,并实现EventArgs类(上述代码中的OrderEventArgs类)

2.依据.net规范,委托的作用是处理事件时,需要在声明时添加EventHandler后缀(上述代码中的OrderEventHandler委托)

事件的简略声明

简略声明

从形式上看事件似乎是字段,但实际上不是。事件之于委托,类似属性之于字段

事件只能出现在+=或-=操作符左侧,但OnOrder函数的if语句中却出现在了!=操作符左侧,原因是此处为C#语法糖(简略声明下,无显式的委托字段,只能如此。Order(this, args)也是出于同样的原因)

public class Customer
{public event OrderEventHandler Order; // 事件public double Bill { get; set; }public void Think(string dishName, string size){Console.WriteLine("Customer: I need {0} {1}", size, dishName);OnOrder("Cake", "Medium");}protected void OnOrder(string dishName, string size){if (Order != null){OrderEventArgs args = new();args.DishName = dishName;args.Size = size;Order(this, args);}}
}

完整声明

public class Customer
{private OrderEventHandler orderEventHandler; // 事件用于接收订阅的委托public event OrderEventHandler Order         // 事件{add{orderEventHandler += value;}remove{orderEventHandler -= value;}}public double Bill { get; set; }public void Think(string dishName, string size){Console.WriteLine("Customer: I need {0} {1}", size, dishName);OnOrder("Cake", "Medium");}protected void OnOrder(string dishName, string size){if (orderEventHandler != null){OrderEventArgs args = new();args.DishName = dishName;args.Size = size;orderEventHandler(this, args);}}
}

实际上大多数情况下可以直接使用C#提供的事件委托(EventHandler)来声明事件,无需自己声明事件委托

但是需要注意EventHandler委托的参数格式是(object? sender, EventArgs e),被委托的函数中需要做里氏转换(此即为何自定义的XXXEventArgs类最好派生自EventArgs类的原因)

private static void Main(string[] args)
{Customer customer = new();Waiter waiter = new();customer.Order += waiter.TakeOrder;customer.Think("Cake", "Medium");
}public class Customer
{public event EventHandler Order;public double Bill { get; set; }public void Think(string dishName, string size){Console.WriteLine("Customer: I need {0} {1}", size, dishName);OnOrder("Cake", "Medium");}protected void OnOrder(string dishName, string size){if (Order != null){OrderEventArgs args = new();args.DishName = dishName;args.Size = size;Order(this, args);}}
}
public class Waiter
{public void TakeOrder(Object customer, EventArgs e){// 里氏转换Customer customer_ = customer as Customer;OrderEventArgs e_ = e as OrderEventArgs;Console.WriteLine("Waiter: I will serve you the dish - {0} {1}", e_.Size, e_.DishName);double basePrice = 10;switch (e_.Size){case "Small":basePrice *= 0.5;break;case "Large":basePrice *= 1.5;break;default:break;}customer_.Bill += basePrice;Console.WriteLine("Waiter: You need to pay ${0}", customer_.Bill);}
}
// 依据.net规范, 类的作用是传递事件信息(EventArgs)时, 需在声明时添加EventArgs后缀, 并实现EventArgs类
public class OrderEventArgs : EventArgs
{public string DishName { get; set; }public string Size { get; set; }
}

结语

事件基于委托,但不等同于委托 

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

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

相关文章

【MySQL高可用集群】MySQL的MGR搭建

前情提要: MySQL官方在 5.7.17版本正式推出组复制(MySQL Group Replication,简称MGR),使用类似 zookeeper 的多于一半原则。在一个集群由 2N1 个节点共同组成一个复制组,一个事务的提交,必须经过…

蛋白结构预测模型评价指标

欢迎浏览我的CSND博客! Blockbuater_drug …点击进入 文章目录 前言一、蛋白结构预测模型评价指标TM-scorelDDT 二、Alphafold中的评价指标pLDDTpTMPAE 三、AlphaFold-multimer 蛋白结构的评价指标DockQipTM 总结参考资料 前言 本文汇总了AlphaFold和AlphaFold-mul…

tigramite教程(二)生物地球科学案例研究

文章目录 数据生成与绘图因果发现分析平稳性假设、确定性、潜在混杂因素结构假设参数假设使用PCMCIplus的滑动窗口分析聚合因果图非参数因果效应估计假设的图形和调整集干预的真实情况假设的参数模型和因果效应的估计使用关于图的不同假设进行估计非因果估计项目地址 这个文件…

android 13.0 屏蔽所有电话来电功能

1.概述 在13.0系统rom定制化开发中,最近项目需要开发需求是屏蔽来电功能,需要根据标志位 屏蔽一切来电功能 就是去掉通话功能,这就需要从通话流程进行分析,然后实现功能 ,而我们知道所有的来电去掉都是CallManager.java来负责监听管理的。 2.屏蔽所有电话来电功能的核心代…

LeetCode_Java_动态规划(2)(题目+思路+代码)

131.分割回文串 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1: 输入:s "aab" 输出:[["a&qu…

算法简介:查找与算法运行时间

文章目录 1. 二分查找与简单查找1.1 运行时间 2. 旅行商问题 算法是一组完成任务的指令。任何代码片段都可以视为算法。 1. 二分查找与简单查找 二分查找是一种算法,其输入是一个有序的元素列表,如果要查找的元素包含在列表中,二分查找返回…

ActiveMq PUT任意文件上传漏洞(CVE-2016-3088)漏洞复现

ActiveMQ ActiveMQ Web控制台分为三个应用程序:其中admin,api和fileserver,其中admin是管理员页面,api是界面,fileserver是用于存储文件的界面;admin和api需要先登录才能使用,fileserver不需要…

门面模式(Facade Pattern)

定义 门面模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;旨在为一个复杂子系统提供一个简单的接口。它提供了一个高层接口&#xff0c;使得客户端可以更容易地使用这个子系统&#xff0c;而不需要了解其内部的复杂性。 示例 #include <ios…

Pytorch安装遇到网络问题

在运行 conda install pytorch1.11.0 torchvision cudatoolkit -c pytorch出现问题 (GAN) D:\0code\vision>conda install pytorch1.11.0 torchvision cudatoolkit -c pytorch Collecting package metadata (current_repodata.json): - DEBUG:urllib3.connectionpool:Star…

元素实现拖拽效果react-dnd+react-dnd-html5-backend

做完案例还是很懵逼 // useDrag 可以让一个 DOM 元素实现拖拽效果 // useDrop 可以让一个 DOM 元素能够放置拖拽元素 参考资料1 //React DnD 参考资料2 https://www.cnblogs.com/dtux/p/17468866.html import React, { useState } from react; import { useDrop, useDra…

Vue开发日志:宏观布局

Vue开发日志&#xff1a;宏观布局 总纲拆分组件化开发&#xff1a;拆分页面模块化开发&#xff1a;拆分功能两者的关系 集成组件传参父组件向子组件传参子组件接收参数子组件向父组件传参父组件接收参数场记 总纲 不识庐山真面目&#xff0c;只缘身在此山中 跳出三界之外&…

TypeScript基础知识点详解

TypeScript基础知识点详解 引言&#xff1a; 在现代前端开发中&#xff0c;TypeScript作为一种静态类型的JavaScript超集&#xff0c;越来越受到开发者的青睐。它提供了类型检查、编译时错误提示、代码重构和智能提示等功能&#xff0c;使得代码更加健壮、可维护。本文将详细介…

AI能不断进化吗?

AI的进化是一个持续的过程&#xff0c;并且随着时间推移和技术的发展&#xff0c;AI可以不断进化。这种进化可以包括以下几个方面&#xff1a; 1、算法和模型的改进&#xff1a; AI的进化可以通过改进其算法和模型来实现。研究人员不断提出新的算法和模型&#xff0c;使得AI在…

c语言中的宏指的是什么

在C语言中&#xff0c;宏&#xff08;Macro&#xff09;是一种预处理器的功能&#xff0c;用于将代码片段命名并用一个标识符替代。宏定义通过 #define 关键字完成&#xff0c;可以用于表示常量、创建函数样式的代码块&#xff0c;以及执行简单的文本替换。 举个例子&#xff…

Linux下定位内存踩踏问题的一种方法

Linux下定位内存踩踏问题的一种方法 演示代码(main.cpp)编译并执行输出 我们在Linux下用C/C开发具有一定复杂性的系统时,需要集成多个部门开发的SDK。内存越界的问题,往往让人头疼。本文提供了一种思路,用来定位内存踩踏。 开发者应该清楚哪块内存不应该被写入(或padding一块只…

IT基础监控与各IT体系模块的深化关系及其作用详解

IT基础监控作为运维工作的“眼睛”和“耳朵”&#xff0c;始终贯穿于自动化、容器化、云原生、团队协作及智能运维的实践中。以下是对IT基础监控与各IT体系模块之间关系的进一步补充和深化。 1. IT基础监控与自动化的深化关系 在自动化运维的实践中&#xff0c;基础监控不仅是…

C++11_C++回顾

范围for 对于一个有范围的集合而言&#xff0c;由程序员来说明循环的范围是很多余的&#xff0c;有时还很容易犯错误。因此C中引入了基于范围for循环。for循环后的括号由冒号":"分为两部分&#xff0c;第一部分是范围内用于迭代的变量&#xff0c;第二部分则表示被迭…

智慧餐饮系统架构的设计与实现

随着科技的不断发展&#xff0c;智慧餐饮系统在餐饮行业中扮演着越来越重要的角色。智慧餐饮系统整合了信息技术&#xff0c;以提高餐饮企业的管理效率、客户服务质量和市场竞争力。本文将探讨智慧餐饮系统架构的设计与实现&#xff0c;并探讨其在餐饮行业中的应用前景。 架构…

大文件上传

分片上传 将文件分为多个大小相等的小块&#xff0c;提高并发 前端将切割的每个分片按顺序传送给后端 后端收到分片后&#xff0c;记录特征信息&#xff08;MD5&#xff09; 按序号进行拼接 断点续传 将文件分为几个小块 每次上传时记录一个块信息&#xff0c;例如文件MD…

matlab采用不同数值方法求解微分方程

1、内容简介 略 60-可以交流、咨询、答疑 欧拉方法、改进欧拉、RK4、米尔斯坦方法求解微分方程 2、内容说明 略 lc; close all; clear all; % 参数赋值 global a global b global h a 1; b 2; Ni 1000; % 总步数 h 0.001; % 步长Xt1(1:Ni) 0; Xt2(…