是什么

本文讨论类型中定义的最后一种成员:事件

定义了时间成员的类型允许类型通知其他对象发生了特定的事情。

具体的说,定义了时间成员的类型能提供以下功能:

  • 方法能登记它对事件的关注
  • 方法能注销它对事件的关注
  • 事件发生时,登记了的方法将收到通知

CLR事件模型以委托为基础。委托是调用回调方法的一种类型安全的方式。

怎么用

本文我们将通过一个小栗子来学习一下事件怎么使用:

假定有个bolg平台可以订阅文章,用户A、B、C可以通过订阅或取消订阅来接收或者不接受此平台的文章。即,我是管理员,我在blog上发了一篇文章,那么订阅blog的用户就可以收到这篇文章了。

下面我们来实现这个功能,顺便来学习下事件的使用:

第一步:定义类型来容纳所有需要发送给事件通知者的附加信息

约定:这种类型应该从System.EventArgs派生,而且类名以EventArgs结束。

internal class BlogEventArgs : EventArgs
{
private readonly String author, content;
private DateTime tdate; public BlogEventArgs(string author,string content,DateTime date)
{
this.author = author;
this.content = content;
this.tdate = date;
} public string Author { get { return author;} }
public string Content { get { return content; } }
public DateTime TDate { get { return tdate;} }
}

第二步:定义事件成员

约定:事件使用event关键字。每个事件成员要指定以下内容:可访问性标识符;委托类型;以及名称。

internal class BlogManager
{
public event EventHandler<BlogEventArgs> NewBlog;
}

第三步:定义负责引发事件的方法来通知事件的登记对象

约定:类要定义一个受保护的虚方法。引发事件时,类及其派生类中的代码回调用该方法。方法只接受一个参数,即BlogEventArgs对象

protected virtual void OnNewBlog(BlogEventArgs e)
{
EventHandler<BlogEventArgs> temp = Volatile.Read(ref NewBlog);
if (temp!=null)
{
temp(this, e);
}
}

关于为什么要像上边这样写,只能说这样是线程安全的方式引发事件,其他方式可能会有线程方面的问题。

第四步:定义方法将输入转化为期望事件

BlogManager中,调用WriteNewBlog来指出写了一篇新博客

public void WriteNewBlog(string author, string content, DateTime date)
{
BlogEventArgs e = new BlogEventArgs(author,content,date);
OnNewBlog(e);
}

第五步:设计侦听事件的类型

比如User类型想订阅或取消这个博客

internal sealed class Reader
{
public Reader(BlogManager blogManager)
{
blogManager.NewBlog += blogManager_NewBlog;
} void blogManager_NewBlog(object sender, BlogEventArgs e)
{
Console.WriteLine("读者已收到博客!");
Console.WriteLine("作者:{0},内容:{1},发表时间:{2}",e.Author,e.Content,e.TDate.ToShortTimeString());
} public void Unregister(BlogManager bmManager)
{
bmManager.NewBlog -= blogManager_NewBlog;
}
}

最后一步使用起来

class Program
{
static void Main(string[] args)
{
BlogManager bmManager = new BlogManager();
Reader readerA =new Reader(bmManager);
bmManager.WriteNewBlog("1号作者", "这是我的第一篇文章", DateTime.Now);
readerA.Unregister(bmManager);
bmManager.WriteNewBlog("1号作者", "这是我的第二篇文章,应该收不到", DateTime.Now);
Console.ReadKey();
}
}

运行


总结

根据书本《CLR via C#》的小栗子自己更改了一点,希望对你有帮助。

带你一步步的了解“C#事件”机制的更多相关文章

  1. ApplicationEvent事件机制源码分析

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

  2. Android自定义View的实现方法,带你一步步深入了解View(四)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了,回 ...

  3. Android视图状态及重绘流程分析,带你一步步深入了解View(三)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17045157 在前面一篇文章中,我带着大家一起从源码的层面上分析了视图的绘制流程, ...

  4. 【转】Android自定义View的实现方法,带你一步步深入了解View(四)

    原文网址: 转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到 ...

  5. Android视图绘制流程完全解析,带你一步步深入了解View(二)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/16330267 在上一篇文章中,我带着大家一起剖析了一下LayoutInflater ...

  6. Android LayoutInflater原理分析,带你一步步深入了解View(一)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/12921889 有不少朋友跟我反应,都希望我可以写一篇关于View的文章,讲一讲Vi ...

  7. JavaScript 详说事件机制之冒泡、捕获、传播、委托

    DOM事件流(event  flow )存在三个阶段:事件捕获阶段.处于目标阶段.事件冒泡阶段. 事件捕获(event  capturing):通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会 ...

  8. 【初窥javascript奥秘之事件机制】论“点透”与“鬼点击”

    前言 最近好好的研究了一番移动设备的点击响应速度,期间不断的被自己坑,最后搞得焦头烂额,就是现在可能还有一些问题,但是过程中感觉自己成长不少, 最后居然感觉对javascript事件机制有了更好的认识 ...

  9. ExtJs的事件机制Event(学员总结)

    一.事件的三种绑定方式 1.HTML/DHTML 在标签中直接增加属性触发事件 [javascript] view plaincopy <script type="text/javas ...

随机推荐

  1. (十五)WebGIS中平移功能的设计和实现

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 这一章我们将详细讲解WebGIS工具栏中另一个基础工具——平 ...

  2. 1.Struts2简介和Struts2开发环境搭建

    一.Struts2简介: 1.什么是Struts2? 著名的SSH三大框架分别为:表现层(Struts).业务逻辑层(Spring),持久化层(Hibernate). Struts2是在WebWork ...

  3. 浅析String不可变性

    在所有编程语言领域,我想字符串应该是地球上最常用的表达手段了吧. 在java的世界里,String是作为类出现的,核心的一个域就是一个char数组,内部就是通过维护一个不可变的char数组,来向外部输 ...

  4. 模拟实现SQL Server中的datepart(week,date)的功能

    本文目录列表: 1.为什么要模拟实现datepart(week,date)的功能 2.具体实现思路 3.T-SQL代码实现逻辑 4.总结语 5.参考清单列表   1.为什么要模拟实现datepart( ...

  5. Javascript 接口模拟

    Javascript接口模拟可以通过三种方式实现文档手段(注释).辅助类和鸭式辨. 第一种和第二种只形式上体现没有真正的实现. 鸭式辨实现原理是:"只要能像鸭子一样叫和走就是鸭子" ...

  6. javascript系统时间测试题

    如果系统的时间是2016年2月20日,分析下列JavaScript代码,运行后在网页上显示() var now = new Date();var year = now.getFullYear();va ...

  7. csharp: Oracle Stored Procedure DAL using ODP.NET

    paging : http://www.codeproject.com/Articles/44858/Custom-Paging-GridView-in-ASP-NET-Oracle https:// ...

  8. csharp: ODP.NET,System.Data.OracleClient(.net 4.0) and System.Data.OleDb读取Oracle g 11.2.0的区别

    ODP.NET: 引用: using Oracle.DataAccess; //Oracle g 11.2.0 using Oracle.DataAccess.Client; using Oracle ...

  9. swift变量和函数

    func getNums()->(Int,Int){ //swift函数可以返回多个变量 ,) } let (a,b) = getNums() //let是常量,一旦赋值后不可改变, var是变 ...

  10. tomcat启动时候报错Can't convert argument: null

    一.启动报错: 为了避免导入的项目重名,我先修改了前一个项目的名称. 重新启动该项目至tomcat,报错:java.lang.IllegalArgumentException: Cant conver ...