C#基础学习--事件

目录

发布者和订阅者

 源代码组件概览

 声明事件

事件是成员

订阅事件

 触发事件

 标准事件的用法

 通过扩展EventArgs来传递数据

泛型委托

 移除事件处理程序  -=

事件访问器


发布者和订阅者

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

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

 一些有关事件的重要事项:

 事件的私有委托:

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

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

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

+=  和 -= 运算符是事件唯一允许的操作(除了调用事件本身)

 源代码组件概览

需要在事件中使用的代码有5部分:

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

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

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

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

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

 声明事件

事件声明在一个类中

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

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

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

 可以通过逗号分隔的列表在一个声明语句中声明一个以上的事件

 可以使用 static 关键字让事件变成静态

事件是成员

由于事件是成员:

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

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

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

订阅事件

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

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

 触发事件

事件成员本身只是保存了需要被调用的事件处理程序。如果时间没有被触发就什么都不会发生

using System;
using System.Collections.Generic;
using System.Text;

namespace Csharpzuoye
{
    delegate void Handler();

    //发布者:
    class Incrementer
    {
        public event Handler CountedADozen;  //创建事件并发布

        public void DoCount()
        {
            for(int i = 1;i<100;i++)
            {
                if (i % 12 == 0 && CountedADozen != null)
                    CountedADozen();  //每增加12个计数触发事件一次
            }
        }
    }

    //订阅者:
    class Dozens
    {
        public int DozensCount { get; private set; }
        //构造函数
        public Dozens(Incrementer incrementer)
        {
            DozensCount = 0;
            incrementer.CountedADozen += IncrementDozensCount;   //订阅事件
        }
        //声明事件处理程序
        void IncrementDozensCount()
        {
            DozensCount++;
        }
    }

    class Program
    {
        static void Main()
        {
            Incrementer incrementer = new Incrementer();
            //构造函数直接订阅事件,一步到位
            Dozens dozensCounter = new Dozens(incrementer);

            incrementer.DoCount();
            Console.WriteLine("Number of dozens = {0}", dozensCounter.DozensCount);
        }
    }
}

 标准事件的用法

GUI编程是事件驱动的,也就是说在程序运行时,它可以在任何时候被事件打断,比如按钮点击,按下按键或系统定时器

 事件使用的标准模式的根本就是System命名空间声明的EventHandler委托类型。

 EventHandler 委托类型的第二个参数是EventArgs类对象,它的声明在System命名空间中

 不管参数使用什么的实际类型是什么,object类和EventArgs总是基类,这样EventHandler就能提供一个对所有事件和事件处理器都通用的签名,只允许两个参数,而不是各自都有不同的签名

标准使用对比:

 通过扩展EventArgs来传递数据

声明一个派生自EventArgs的自定义类,可以保存我们传入的数据,向事件处理程序的第二个参数传入数据

类的名称应该以EventArgs结尾

泛型委托

 移除事件处理程序  -=

事件访问器

猜你喜欢

转载自blog.csdn.net/zaizai1007/article/details/130179211