详解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
猜你喜欢
- 动态数组ArrayList类在System.Collecions的命名空间下,所以使用时要加入System.Collecions命名空间,而
- 1. 配置MailPlugin插件public void configPlugin(PluginLoader pluginLoader) {
- Java RandomAccessFile 指定位置实现文件读取与写入RandomAccessFile是属于随机读取类,是可以对文件本身的内
- java读取文件内容,解析Json格式数据一、读取txt文件内容(Json格式数据) public static
- mybatis的原身是ibatis,现在已经脱离了apache基金会,新官网是http://www.mybatis.org/。在研究Myba
- 本文实例讲述了Java基于链表实现栈的方法。分享给大家供大家参考,具体如下:在上几小节中我们实现了基本的链表结构,并在上一节的底部给出了有关
- spring @Autowired注解无法注入问题简述在使用spring框架的过程中,常会遇到这种两情况:1、在扫描的包以外使用需要使用ma
- 1、异常分类通常分为三类:系统异常(SystemException),业务异常(BusinessException)和其他异常(Except
- 线程安全当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协调,这个类
- 本文主要是分析Spring bean的循环依赖,以及Spring的解决方式。 通过这种解决方式,我们可以应用在我们实际开发项目中。1. 什么
- java.util.Arrays类能方便地操作数组,它提供的所有方法都是静态的。静态方法是属于类的,不是属于类的对象。所以可以直接使用类名加
- 实现官方文档说明:com.baomidou.mybatisplus.annotations.TableFieldTableField注解新增
- import java.util.ArrayList;import java.util.Collections;import java.ut
- QueryWrapper条件构造之apply、last、select场景: 查询数据库限制条数时mysql上的limit使用 Qu
- 项目最终的文件结构1 添加maven依赖 <dependency> <groupI
- 6.0的手机对于写入手机需要申请权限的我做了如下处理下面我贴出代码package com.example.admin.sdapplicati
- 从接收输入值说起在日常的开发应用中,有时候需要直接接收外部设备如键盘等的输入值,而对于这种数据的接收方式,我们一般有三种方法:字节流读取,字
- 具体可见http://developer.android.com/tools/debugging/ddms.html。 DDMS为IDE和e
- 目录为什么要使用 TaskTask 和 Thread 区别Task 介绍Task 简单实现Task 执行状态1.等待(Wait)2. 返回值
- springboot远程debug调试1.首先去编辑器打开项目2.打开Edit Configurations 选择remote选项