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

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

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

在典型的 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

最新文章

  1. 一步一步开发Game服务器(二)登陆2
  2. 【转】编译Lua5.3.0的iOS静态库
  3. ActiveX 技术疑点 一
  4. Spring AOP Example – Advice
  5. SQL Server 2005恢复数据库详细图文教程
  6. [个人原创]关于java中对象排序的一些探讨(一)
  7. Android - FragmentTabHost 与 Fragment 制作页面切换效果
  8. 201521123060 《Java程序设计》第9周学习总结
  9. MapReduce编程(一) Intellij Idea配置MapReduce编程环境
  10. Git-gitblit-Tortoisegit 搭建Windows Git本地服务器
  11. Django-CSRF的使用
  12. 一个入门rpc框架的学习
  13. [转载]使用QTP测试Windows对象
  14. HDU 2612 - Find a way - [BFS]
  15. Java——java错误(The Struts dispatcher cannot be found)
  16. urb的处理流程
  17. Vue那些事儿之用visual stuido code编写vue报的错误Elements in iteration expect to have 'v-bind:key' directives.
  18. 【刷题】BZOJ 1969 [Ahoi2005]LANE 航线规划
  19. Android Studio 中实现高德定位并获取相应信息
  20. C# 装箱和拆箱[整理](转)

热门文章

  1. C# 中获取CPU序列号/网卡mac地址
  2. cocos2d-x 3.9 android studio项目命令行打包
  3. NULL 与空字符串
  4. 7 Python 数据类型—列表
  5. php 实现分享到QQ空间 新浪微博
  6. JSP分页1
  7. 常规DLL与扩展DLL区别
  8. noip前打板子 qwq
  9. bzoj 4504: K个串 可持久化线段树+堆
  10. docker 局域网仓库(registry)