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

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

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

在典型的 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. EntityFramework 学习 一 枚举

    1. Convert an existing property to Enum: using (var ctx = new SchoolDBEntities()) { Teacher tchr = n ...

  2. jquery的几个语法总结和注意事项

    1.关于页面元素的引用 通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用do ...

  3. Java -- Swing 组件使用

    1. 示例1 public class Main { JFrame f = new JFrame(); Icon okIcon = new ImageIcon("/home/test/sta ...

  4. strnpy函数

    函数原型: char * strncpy ( char * destination, const char * source, size_t num ); 功能:从字符串source中复制 num个字 ...

  5. JS+css3焦点轮播图PC端

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. C++quickSort

    void QuickSort1(int *s,int left,int right){ int i,j,t,pivot; if(left>right) return; if(left<ri ...

  7. HDU - 5934

    tarjan 视频讲解 /** * 题目链接:https://vjudge.net/problem/HDU-5934 * 题意:给你n个炸弹,引爆每个炸弹会有一定的花费.每个炸弹给出坐标x,y,半径r ...

  8. VS2019(Windows+Mac)编辑文件模板

    macOS 找到设置中的如图条目 设置如下内容: ============================================================ Copyright (C) ...

  9. 如果你使用WebView+FloatingActionButton

    在WebView中想要使用FAB,如果你想向上滑动的时候隐藏FAB,那么需要再WebView外面套一个ScrollView! 原因之前也分析过,和为什么ListView不能让ToolBar.Tab隐藏 ...

  10. 【原创】C++实现获取本机机器名及外网IP代码

    上代码: #include "stdafx.h" #include <WINSOCK2.H> #include <urlmon.h> #pragma com ...