讲过了委托,不得不讲事件。

事件基于委托,为委托提供了一种发布/订阅机制。

在发生其他类或对象关注的事情时,类或对象可通过事件通知它们。发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。

在典型的 C# Windows 窗体或 Web 应用程序中,可订阅由控件(如按钮和列表框)引发的事件。可使用 Visual C# 集成开发环境 (IDE) 来浏览控件发布的事件,选择要处理的事件。IDE 会自动添加空事件处理程序方法和订阅事件的代码。

事件时对委托的封装。

事件帮助解决委托封装问题。事件位于委托的顶部,并提供封装,使得目标源只能听而不能完全控制的委托对象。

下图显示了事件的样子: -

理解事件:

Button是一个类,当你点击按钮的时候,Click事件被触发。

定时器是一个类,每毫秒tick事件被触发。

下面通过一个例子来讲述一下事件的应用。

定义两个类CarDealer和Consumer。CarDealer类提供了一个新车到达时触发的事件,Consumer类订阅该事件,以获得新车到达的通知。

事件发布程序:CarDealer类提供了EventHandler类型的NewCarInfo事件。事件一般使用带两个参数的方法。第一个参数是一个对象,包含事件的发送者;第二个参数提供了事件的相关信息。

你可能感到吃惊,没有定义委托怎么就定义事件了??其实有了泛型委托EventHandler 委托后,就不再需要委托了。

EventHandler 的语法如下:

public delegate void EventHandler(Object sender,TEventArgs e) where TEventArgs : EventArgs

EventHandler定义了一个处理程序,返回void,接受两个参数。第一个参数必须是object,第二个参数是T类型,对于T有一个约束,就是它必须派生自基类EventArgs。下面代码的CarInfoEventArgs就派生自基类EventArgs.

EventArgs是包含事件数据的类的基类,此类不包含事件数据,在事件引发时不向事件处理程序传递状态信息的事件会使用此类。如果事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。事件处理程序委托的标准签名定义一个没有返回值的方法,其第一个参数的类型为 Object,它引用引发事件的实例,第二个参数从 EventArgs 类型派生,它保存事件数据。 如果事件不生成事件数据,则第二个参数只是 EventArgs 的一个实例。 否则,第二个参数为从 EventArgs 派生的自定义类型,提供保存事件数据所需的全部字段或属性。

EventHandler 是一种预定义委托,表示事件的事件处理程序方法,它与事件是否生成事件数据无关。 如果事件不生成事件数据,则用 EventArgs 替代泛型类型参数;否则,提供自己的自定义事件数据类型并用该类型替代泛型类型参数。

使用 EventHandler 的优点在于,如果事件生成事件数据,则无需编写自己的自定义委托代码。 此外,.NET Framework 只需一个实现就能支持 EventHandler ,这与替代泛型类型参数的事件数据类型无关。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestEvent
{
public class CarInfoEventArgs:EventArgs
{
public CarInfoEventArgs(string car)
{
this.Car = car;
}
public string Car{get; private set;}
}
public class CarDealer
{
public event EventHandlerNewCarInfo;
public void NewCar(string car)
{
Console.WriteLine("CarDealer. new car {0}", car);
if (NewCarInfo != null)
{
NewCarInfo(this, new CarInfoEventArgs(car));
}
}
}
}

事件监听器:Consumer类用作事件侦听器。这个类订阅了CarDealer类的事件,并定义了NewCarIsHere方法,该方法满足EventHandler委托的要求,其参数类型是object和CarInfoEventArgs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestEvent
{
class Consumer
{
private string name;
public Consumer(string name)
{
this.name = name;
}
public void NewCarIsHere(object sender, CarInfoEventArgs e)
{
Console.WriteLine("{0}: car {1} is new", name, e.Car);
}
}
}

现在需要连接事件发布器和订阅器。使用“+=”创建一个订阅。使用“-=”取消了订阅。使用代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestEvent
{
class Program
{
static void Main(string[] args)
{
var dealer = new CarDealer();
var michael = new Consumer("Michael");
dealer.NewCarInfo += michael.NewCarIsHere;
dealer.NewCar("Mercedes");
var nick = new Consumer("Nick");
dealer.NewCarInfo += nick.NewCarIsHere;
dealer.NewCar("Ferrari");
dealer.NewCarInfo -= michael.NewCarIsHere;
dealer.NewCar("Toyota");
}
}
}
/*-------------------------------------
输出结果:
CarDealer. new car Mercedes
Michael: car Mercedes is new
CarDealer. new car Ferrari
Michael: car Ferrari is new
Nick: car Ferrari is new
CarDealer. new car Toyota
Nick: car Toyota is new
---------------------------------------*/
https://www.cnblogs.com/sjqq/p/6918006.html

浅析C#中的事件的更多相关文章

  1. 浅析 JavaScript 中的 函数 currying 柯里化

    原文:浅析 JavaScript 中的 函数 currying 柯里化 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字 ...

  2. 浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程【转】

    本文转载自:http://www.cnblogs.com/qingchen1984/p/7007631.html 本篇文章主要介绍了"浅析 Linux 中的时间编程和实现原理一—— Linu ...

  3. 深入浅析python中的多进程、多线程、协程

    深入浅析python中的多进程.多线程.协程 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源 ...

  4. C++中的事件分发

    本文意在展现一个C++实现的通用事件分发系统,能够灵活的处理各种事件.对于事件处理函数的注册,希望既能注册到普通函数,注册到事件处理类,也能注册到任意类的成员函数.这样在游戏客户端的逻辑处理中,可以非 ...

  5. javascript中的事件冒泡和事件捕获

    1.事件冒泡 IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档).以下面的HTML ...

  6. jQuery文本框中的事件应用

    jQuery文本框中的事件应用 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht ...

  7. 怎么理解js中的事件委托

    怎么理解js中的事件委托 时间 2015-01-15 00:59:59  SegmentFault 原文  http://segmentfault.com/blog/sunchengli/119000 ...

  8. jQuery中的事件绑定方法

    在jQuery中,事件绑定方法大致有四种:bind(),live(), delegate(),和on(). 那么在工作中应该如何选择呢?首先要了解四种方法的区别和各自的特点. 在了解这些之前,首先要知 ...

  9. 四、jquery中的事件与应用

    当用户浏览页面时,浏览器会对页面代码进行解释或编译--这个过程实质上是通过时间来驱动的,即页面在加载时,执行一个Load事件,在这个事件中实现浏览器编译页面代码的过程.时间无论在页面元素本身还是在元素 ...

随机推荐

  1. maven 相关插件

    maven打包配置,到底要打包哪些文件,如何配置??使用如下插件: <build> <finalName>weatherAdminSys</finalName> & ...

  2. JavaWeb -- Session应用实例 -- 随机中文验证码 检验

    注册页面 login.html <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html ...

  3. Python的进度条的制作

    import sys,time #导入模块 for i in range(50): #进度条的长度 sys.stdout.write("#") #进度条的内容,这里要注意了,pyc ...

  4. windows下安装配置nginx

    下载nginx-1.0.11.zip, 解压到到nginx目录下 D:\nginx\conf 修改conf下的nginx.conf文件, 默认是80端口,若该端口被占则可以修改 listen 8073 ...

  5. Hibernate学习---第十三节:hibernate过滤器和拦截器的实现

    一.hibernate 过滤器 1.在持久化映射文件中配置过滤器,代码如下: <?xml version="1.0"?> <!DOCTYPE hibernate- ...

  6. Serblet 过滤器(Filter)

    Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息. 过滤器的作用: 1.身份验证过滤器 2.日志记录和审核过滤器 3.触发资源访问事件过滤器. 等等等... Ser ...

  7. Redis安装以及基本操作命令

    Redis安装 cd redis-2.6.14make PREFIX=/usr/local/redis install 可能会出现的错误提示>>提示1:make[3]: gcc:命令未找到 ...

  8. java--xml文件读取(DOM)

    1.表现:一“.xml”为扩展名的文件 2.存储:树形结构 3.xml解析应用: 不同应用程序之间的通信-->订票软件和支付软件 不同的平台间通信-->操作系统 不同平台间数据的共享--& ...

  9. FFmpeg 的sws_getContext函数 、sws_scale函数

    FFmpeg里面的sws_scale库可以在一个函数里面同时实现:1.图像色彩空间转换:2.分辨率缩放:3.前后图像滤波处理. 其核心函数主要有三个: // 初始化sws_scalestruct Sw ...

  10. 错误名称:Uncaught SyntaxError: Unexpected token <

    在AngularJS框架下:   控制台输出: 1.谷歌:Uncaught SyntaxError: Unexpected token < 2.火狐:SyntaxError: expected ...