C# 事件
时间:2022-07-24
本文章向大家介绍C# 事件,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
零、广播者和订阅者
使用委托的时候通常会出现两个角色,分别是广播者和订阅者。广播者包含委托字段,通过调用委托来决定何时进行广播。订阅者是方法目标的接收者,订阅者决定什么时候开始监听和结束监听,开始监听在委托上使用+=,结束监听在委托上使用-=。.NET环境下,一个订阅之不知道其他订阅者的存在,同时也不会干扰其他订阅者。
一、事件
事件(Event) 是一种结构,将广播/订阅模式正式化为语言特性,并且只暴漏所需的委托特性的部分子集。事件存在的主要目的是防止订阅者相互干扰。
- 声明事件 声明事件只需在委托前面加上 event 关键字即可。例子如下:
public delegate void StudentHandler(string name);
public class School
{
public event StudentHandler student;
// more code
// ......
}
这里我们来解释一下上面的代码,我们在代码外侧定义了一个委托 StudentHandler ,并且在类 School 中定义了一个事件。在这段代码中 School 类中的所有代码可以把 student 完全当作委托来使用。但是在 School 类外部只能对 student 这个时间执行 +=和-=操作。
- 事件模式 .NET中有一个预定义框架类 System.EventArgs ,其中只有静态属性 Empty,所有的传递信息的类都必须继承自这个预定义框架类。 我们来通过一个例子来看一下:
public class SchoolEventArgs:System.EventArgs
{
public readonly string Name;
public SchoolEventArgs(string name)
{
Name = name;
}
}
上面代码中的只读字段 Name 是我们要传递的信息,一般情况下要传递的信息会使用 属性 或者 只读字段。
当我们编写完传递信息的类之后,就需要为事件定义委托了,为事件定义委托有如下几个硬性要求:
- 返回类型必须是 void ;
- 必须接受两个参数,第一个参数是 object (事件的广播者) ,第二个参数是 EventArgs 的子类 (要传递的信息);
- 名称必须以 EventHandler 结尾
下面我们就行定义事件,定义事件就简单了,例子如下:
public delegate void StudentHandler(string name);
public class School
{
public event StudentHandler student;
}
定义完事件之后还需要定义触发事件的方法,触发时间的方法也有如下两点要求:
- 方法必须以 protected 修饰;
- 方法名命名必须是 On事件名* 的格式,并且接受一个 EventArgs 参数。
我们来看一下代码:
public delegate void StudentEventHandler(object source, SchoolEventArgs e);
public class School
{
string name;
public event StudentEventHandler studentEventHandler;
protected virtual void OnStudentHandlerEventHandler(SchoolEventArgs e)
{
studentEventHandler?.Invoke(this,e);
}
public string Name
{
get { return name; }
set
{
name = value;
OnStudentHandlerEventHandler(new SchoolEventArgs(name));
}
}
}
到现在为止,我们该定义的都定义完了,现在我们来看一下怎么调用:
class Program
{
static void Main(string[] args)
{
School school = new School();
school.studentEventHandler += School_studentEventHandler;
school.Name = "李四";
Console.Read();
}
private static void School_studentEventHandler(object source, SchoolEventArgs e)
{
Console.WriteLine(e.Name);
}
}
执行上述代码,得到如下结果:
- 探秘Tomcat——连接器和容器的优雅启动
- 谈谈分布式事务之三: System.Transactions事务详解[上篇]
- WCF技术剖析之十九:深度剖析消息编码(Encoding)实现(上篇)
- 谈谈分布式事务之二:基于DTC的分布式事务管理模型[下篇]
- 孙明俊:人工智能之算力演进
- 探秘Tomcat——一个简易的Servlet容器
- 2017年与机器学习相关的10大Python开源库
- 控制并发访问的三道屏障: WCF限流(Throttling)体系探秘[上篇]
- 探秘Tomcat——从一个简陋的Web服务器开始
- EnterLib PIAB又一个BUG?[续]——这是一个致命的BUG
- Google工程师:谷歌翻译在几个月内效果明显提升的秘诀
- 回调与并发: 通过实例剖析WCF基于ConcurrencyMode.Reentrant模式下的并发控制机制
- EnterLib PIAB又一个BUG?[续]——这是一个致命的BUG
- 年终盘点2017年发生在上海的科技大新闻
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Typecho如何添加“编辑”当前文章按钮
- Flutter入门第二讲:项目运行,Hello world
- Flutter入门第一讲:环境搭建(mac os为例)
- 第12天:NLP补充——HMM(隐马尔科夫模型)
- android View事件分发实测
- LeetCode51|寻找旋转排序数组中的最小值
- Yapi 可视化接口平台安装实践
- LeetCode50|搜索旋转排序数组II
- LeetCode49|搜索旋转排序数组
- 第13天:NLP补充——RNN算法
- Android自定义跑马灯效果(适合任意布局)
- Handler Looper.prepareMainLooper();源码分析
- Caused by: java.lang.IllegalStateException: System services not available to Activities before onCre
- Actuator与服务监控
- Typecho 文章置顶插件:Sticky