• review——C# (13)事件


    FROM P255

    1.发布者和订阅者

      很多程序都有一个共同的需求,即当一个特定的程序事件发生时,程序的其他部分可以得到该事件已经发生的通知。

      发布者/订阅者模式(publisher/subscriber pattern)可以满足这种需求。在这种模式中,发布者类定义了一系列程序的其他部分可能感兴趣的事件。其他程序可以“注册”,以便在这些事件发生时发布者可以通知它们。这些订阅者类通过向发布者提供一个方法来“注册”以获取通知。当事件发生时,发布者“触发事件”,然后执行订阅者提交的所有事件。

      由订阅者提供的方法称为回调方法,因为发布者通过执行这些方法来“往回调用订阅者的方法”,还可以将它们称为事件处理程序,因为它们是为处理事件而调用的代码。

    如下图所示:

    以下为一些关于事件的重要事项:

    发布者(publisher)发布某个事件的类或结构,其他类可以在该事件发生时得到通知

    订阅者(subscriber)注册并在事件发生时得到通知的类或结构

    □事件处理程序(event handler)由订阅者注册到事件的方法,在发布者触发事件时执行。事件处理程序可以定义在事件所在的类或结构中,也可以定义在不同的类或结构中。

    触发(raise)事件 调用(invoke)或触发(fire)事件的术语。当事件触发时,所有注册到它的方法都会被依次调用。

    事件就像是专门用于某种特殊用途的简单委托。

    有关事件的私有委托需要了解的重要事项如下。

    □事件提供了对它的私有控制委托的结构化访问。即,你无法直接访问委托

    □事件中可用的操作比委托要少,对于事件我们只可以添加、删除或调用事件处理程序。

    □事件被触发时,它调用委托来依次调用调用列表中的方法。

    2.源代码组件概览

    需要在事件中使用的代码有5部分。这些组件如下所示:

    □委托类型声明  事件和事件处理程序必须有共同的签名和返回类型,它们通过委托类型进行描述。

    □事件处理程序声明  订阅者类中会在事件触发时执行的方法声明。它们不一定是有显示声明的方法,还可以是匿名方法orLambda表达式。

    □事件声明  发布者必须声明一个订阅者可以注册的事件成员。当声明的事件为public时,称为发布了事件

    □事件注册  订阅者必须订阅事件才能在它被触发时得到通知。

    □触发事件的代码  发布者中“触发”事件并导致调用注册的所有事件处理程序的代码。

    3.声明事件

    发布者类必须提供事件对象。创建事件比较简单——只需要委托类型和名字。

    e.g.

    注意到:

    □事件声明在一个类中

    它需要委托类型的名称,任何附加到事件(如注册)的处理程序都必须与委托类型的签名和返回类型匹配

    它声明为public;这样其他类和结构可以在它上面注册事件处理程序。

    □不能使用对象创建表达式(new表达式)来创建它的对象

     

    事件是成员

    由于此

    □不能在一段可执行代码中声明事件

    □它必须声明在类或结构中,和其他成员一样。

     并且

    □事件成员被隐式自动初始化为null

    事件声明需要委托类型的名字。我们可以声明一个委托类型或使用已存在的。如果我们声明一个委托类型,它必须指定事件保存的方法的签名和返回类型。

    BCL声明了一个叫做EventHandler的委托,专门用于系统事件。

    4.订阅事件

    订阅者向事件添加事件处理程序。对于一个要添加到事件的事件处理程序来说,它必须具有与事件的委托相同的返回类型和签名。

    □使用+=运算符来为事件增加事件处理程序

    □事件处理程序的规范可以是以下任意一种:

    --实例方法的名称

    --静态方法的名称

    --匿名方法

    --Lambda表达式

    5.触发事件

    □在触发事件之前和null进行比较,从而查看是否包含事件处理程序,如果事件是null,则表示没有,不能执行

    □触发事件的语法和调用方法一致

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace review
     8 {
     9     delegate void Handler();//声明委托
    10     class Incrementer
    11     {
    12         public event Handler CountedADozen;//创建事件并发布
    13         public void DoCount()
    14         {
    15             for (int i = 1; i < 100; i++)
    16                 if (i % 12 == 0 && CountedADozen != null)
    17                     CountedADozen();
    18         }
    19     }
    20     class Dozens
    21     {
    22         public int DozenCount { get;private set;}
    23         public Dozens(Incrementer incrementer)
    24         {
    25             DozenCount = 0;
    26             incrementer.CountedADozen += IncrementDozensCount;
    27         }
    28         void IncrementDozensCount()
    29         {
    30             DozenCount++;
    31         }
    32 
    33 
    34     }
    35     class Program
    36     {
    37         static void Main(string[] args)
    38         {
    39             Incrementer incrementer = new Incrementer();
    40             Dozens dozensCounter = new Dozens(incrementer);
    41             incrementer.DoCount();
    42             Console.WriteLine(dozensCounter.DozenCount);
    43             Console.Read();
    44         }
    45     }
    46 }
    47 /*
    48  * 输出如下:
    49  * 8
    50  * */

    6.标准事件的用法

    对于事件的使用,.NET框架提供了一个标准模式。事件使用的标准模式的根本就是System命名空间声明的EventHandler委托类型。

    其声明如下:

    1     public delegate void EventHandler(object sender, EventArgs e);

    需要注意:

    □第一个参数用来保存触发事件的对象的引用。由于是object类型的,所以可以匹配任何类型的实例

    □第二个参数用来保存状态信息,指明什么类型适用于该应用程序

    □返回类型是void

     EventArgs类声明在System命名空间中

    □EventArgs设计为不能传递任何数据。它用于不需要传递数据的事件处理程序——通常会被忽略

    □若希望传递数据,必须声明一个派生自EventArgs的类,使用适合的字段来保存需要传递的数据

     (详见P262)

  • 相关阅读:
    LNMP状态管理命令
    Gogs基本使用介绍
    初探Asp.net请求机制原理 1
    关于css定位
    JS不同浏览器图片载入处理
    js之队列01
    javascript 快速排序
    JavaScript prototype背后的工作原理
    关于javascrpt if快速判断说明
    js动态加载图片核心代码
  • 原文地址:https://www.cnblogs.com/quintessence/p/9125283.html
Copyright © 2020-2023  润新知