详解C#之事件
作者:千金不如一默 发布时间:2022-01-07 22:18:14
事件:定义了事件成员的类允许通知其他其他对象发生了特定的事情。具体的说,定义了事件成员的类能提供以下功能
1.方法能登记它对事件的关注
2.方法能注销它对事件的关注
3.事件发生时,登记了的方法将收到通知
类型之所以能提供事件通知功能,是因为类型维护了一个已登记方法的列表。事件发生后,类型将通知列表中所有已登记的方法。
事件是以委托为基础。委托是调用回调方法的一种类型安全的方式。对象凭借回调方法接收他们订阅的通知。
假如有一下场景:要设计一个电子邮件程序。当有新的邮件的到达时,用户希望做些一别的操作,例如转发给其他人或其他想实现的功能。事件在其中起到的就是一个通知的作用,告诉其他对象有新的邮件到达了,可以做XXX事情了。
下面使用事件实现这个功能
1.定义一个附加信息类,用来通知接收者发生了什么。
/// <summary>
/// 事件附加消息
/// </summary>
public class NewMailEventArgs:EventArgs{
private readonly string m_from,m_to,m_subject;
public NewMailEventArgs(string from,string to,string subject){
m_from=from;
m_to=to;
m_subject=subject;
}
// 发件人
public string From { get{return m_from;} }
// 接收人
public string To { get{return m_to;} }
// 主题
public string Subject{get{return m_subject;}}
}
附加信息类继承了EventArgs,这个基类只定义了一个空的信息,在没有附加信息时可直接使用EventArgs.Empty。EventArgs类的源代码
namespace System
{
//
// Summary:
// Represents the base class for classes that contain event data, and provides a
// value to use for events that do not include event data.
public class EventArgs
{
//
// Summary:
// Provides a value to use with events that do not have event data.
public static readonly EventArgs Empty;
//
// Summary:
// Initializes a new instance of the System.EventArgs class.
public EventArgs();
}
}
2.定义事件成员
事件成员使用C#关键字event定义。每个事件成员都要指定以下内容:可访问标识符public(因为只有publi才能使其他对象访问),委托类型以及名称。
public class MailManager{
// 定义事件成员
public event EventHandler<NewMailEventArgs> NewMail;
}
它的类型是EventHandler<NewMailEventArgs> 这意味着事件通知的所有接收者都必须有一个和这个类型匹配的回调方法。System.EventHandler的委托定义类型如下:
namespace System
{
//
// Summary:
// Represents the method that will handle an event when the event provides data.
//
// Parameters:
// sender:
// The source of the event.
//
// e:
// An object that contains the event data.
//
// Type parameters:
// TEventArgs:
// The type of the event data generated by the event.
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
}
所以接收者必须提供的方法必须是一下形式:
void MethodName(Object sender,NewMailEventArgs e);
3. 定义负责引发事件的方法来通知事件的登记对象
public class MailManager{
// 定义事件成员
public event EventHandler<NewMailEventArgs> NewMail;
// 定义负责引发事件的方法来通知已登记的对象
protected virtual void OnNewMail(NewMailEventArgs e){
// 将字段复制到一个临时变量,避免多线程情况中这个成员被移除
EventHandler<NewMailEventArgs> temp=Volatile.Read(ref NewMail);
if(temp!=null) temp(this,e);
}
// 接受附加信息并调用引发事件的方法来通知所有登记的对象
public void SimulateNewMail(string from,string to,string subject){
NewMailEventArgs e=new NewMailEventArgs(from,to,subject);
OnNewMail(e);
}
}
4. 定义事件接收者
public class Fax{
public Fax(MailManager mm){
// 构造委托实例,向事件登记回调方法
mm.NewMail+=FaxMsg;
}
/// <summary>
/// 回调方法
/// </summary>
/// <param name="sender">表示MailManager对象,便于将信息传递给他</param>
/// <param name="e">表示MailManager对象想传给我们的附加信息</param>
private void FaxMsg(object sender,NewMailEventArgs e){
Console.WriteLine("msg:{0},{1},{2}",e.From,e.To,e.Subject);
}
/// <summary>
/// 注销对事件的登记
/// </summary>
/// <param name="mm"></param>
public void Unregister(MailManager mm){
mm.NewMail-=FaxMsg;
}
}
对象不在接收事件通知时应注销对事件的关注。因为对象只要向事件等急了它的一个方法,便不能被垃圾回收。
5. 程序初始化时应首先构造MailManager对象,将指向它的变量传递给Fax。在Fax构造器中添加对事件的关注。最后调用MailManager对象的事件通知方法
static void Main(string[] args)
{
MailManager mm=new MailManager();
Fax f=new Fax(mm);
mm.SimulateNewMail("a","b","Hello World!");
Console.ReadKey();
}
控制台输出结果:以调用回调方法。
来源:https://www.cnblogs.com/jixiaosa/p/10584436.html


猜你喜欢
- 1、数组的定义先声明后使用数据类型 [] 数组名称 = new 数据类型[长度];String[] arr3 = new String[5]
- 一、swagge简介前后端分离:后端︰后端控制层,服务层,数据访问层【后端团队】前端:前端控制层,视图层【前端团队】前后端通过API进行交互
- 仿水波纹流球进度条控制器,Android实现高端大气的主流特效,供大家参考,具体内容如下效果图:CircleView这里主要是实现中心圆以及
- Android onClick 与 setOnClickListener区别为Android Widgets添加点击事件处理函数又
- 前言我在上一篇文章聊了Redisson的分布式锁,这次继续来聊聊Redisson的公平锁。下面是官方原话:它保证了当多个Redisson客户
- 说明一下性能方面 还可以接受 循环1000次普通Switch是用了0.001秒 ,扩展函数为0.002秒 , 如果是大项目在有负
- 概述动态SQL:SQL语句会随着用户输入或外部条件的变化而变化 。例如:我们在做多条件查询的时候,编写SQL语句的查询操作,我们并不知道用户
- 堆排序是一种树形选择排序方法,它的特点是:在排序的过程中,将array[0,...,n-1]看成是一颗完全二叉树的顺序存储结构,利用完全二叉
- ?随着互联网的快速发展,各种组件层出不穷,需要框架集成的组件越来越多。每一种组件与Spring容器整合需要实现相关代码。SpringMVC框
- 本文实例讲述了Android实现将应用崩溃信息发送给开发者并重启应用的方法。分享给大家供大家参考,具体如下:在开发过程中,虽然经过测试,但在
- 自己写了一个Swap测试类,代码如下:swap不能交换原生数据类型以及字符串类型。public class Swap5{ public st
- 本文实例讲述了C#使用foreach语句遍历队列(Queue)的方法。分享给大家供大家参考。具体如下:using System;using
- 该系统分为前台和后台,前台可以自主注册,后台管理员角色,除基础脚手架外,实现的功能有:后台管理员功能有:商品分类管理、商品管理、套餐管理、新
- 你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏。此时有100名学生在上课。游戏的规则是:1. 你首先说出三个不同的特殊数,
- Java类之间的关系图在Java以及其他的面向对象设计模式中,类与类之间主要有6种关系,他们分别是:依赖、关联、聚合、组合、继承、实现。他们
- 一、前言:垃圾回收:在未来的JDK中可能G1会为ZGC所取代先问自己几个问题:什么是垃圾?垃圾就是堆内存中(范指)没有任何指针指向的对象实体
- 知识点:内部存储空间获取总大小和可用大小;sdcard存储空间获取总大小和可用大小;新名词记录{StatFs:描述文件系统信息的类}概览在开
- 什么是粘包/拆包 一般所谓的TCP粘包是在一次接收数据不能完全地体现
- 为什么使用Swagger 在实际开发中我们作为后端总是给前端或者其他系统提供接口,每次写完代码之后不可避
- 国家气象局提供了三种数据的形式网址在:http://www.weather.com.cn/data/sk/101010100.htmlhtt