事件

         事件是一种特殊类型的委托。

1   事件基础

         当某个类或是对象想把自身的状况通知给另外一个类或是对象时,而类或对象在接收到通知(以下便使用术语事件)时,可能需要做出某些处理,但在定义发出事件的类时,一般是不知道接收方应当做何种处理,而事件的出现能很好的解决这个问题。

         发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。

1.1  事件原理

         事件是一种特殊类型的委托,C#采用委托模型来实现事件。发行者首先定义委托,然后使用该委托定义事件,可以简单的认为该事件就是委托,然后,当发行者需要发送(或引发)事件时,就调用事件;而订户则按照事件定义处理程序,然后把处理程序注册到发行者中的事件上,在实例化发行者后,发送(或引用)事件,便会调用相应的事件处理程序。

         如下示例(摘取《.Net 之美》)。

    // 热水器
    public class Heater 
    {
        private int temperature;
        public delegate void BoilHandler(int param); //声明委托
        public event BoilHandler BoilEvent; //声明事件
         // 烧水
        public void BoilWater() {
            for (int i = 0; i <= 100; i++) 
            {
                temperature = i;
                if (temperature > 95) 
                {
                    if (BoilEvent != null)
                    { //如果有对象注册
                        BoilEvent(temperature); //调用所有注册对象的方法
                    }
                }
            }
        }
    }
    // 警报器
    public class Alarm 
    {
        public void MakeAlert(int param) 
        {
            Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", param);
        }
    }
    // 显示器
    public class Display
    {
        public static void ShowMsg(int param)
        { //静态方法
            Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", param);
        }
    }
    class Program
    {
        static void Main()
        {
            Heater heater = new Heater();
            Alarm alarm = new Alarm();
            heater.BoilEvent += alarm.MakeAlert; //注册方法
            heater.BoilEvent += (new Alarm()).MakeAlert; //给匿名对象注册方法
            heater.BoilEvent += Display.ShowMsg; //注册静态方法
            heater.BoilWater(); //烧水,会自动调用注册过对象的方法
        }
    }

         程序的意思是有一个热水器,当水温大于95摄氏度时,发出警报并显示水温。程序定义了热水器类,在其中声明委托和事件,接着定义了报警器类和显示器类,并在主方法中实例它们,进而进行方法注册,在调用热水器加热方法时,便会引发事件,进而执行相应的处理方法。

         输出结果如下。

Alarm:嘀嘀嘀,水已经 96 度了:

Alarm:嘀嘀嘀,水已经 96 度了:

Display:水快烧开了,当前温度:96 度。

//省略...

1.2  事件概述

         前面简要说明了事件的原理,下面将对事件的几个构成分别叙述。

         事件声明:在早期的版本中声明一个事件,必须有一个已经声明好的委托,用以说明事件的类型,在前面热水器程序中就是使用该种方式。在后来的不多发展中,提出了.NET Framework 准则的事件,由于类库中的所有事件均基于 EventHandler 委托,所以只需要声明事件,定义如下:

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

         使用后种方式将使得事件的使用较为简单。

         事件处理程序:在订户中实现对事件的处理,如前面的报警器类中的方法警报的方法,由于需要向发行者注册,所以必须与委托类型一致(特殊情况是变体,通过协变或逆变,可以实现符合参数的不一致)。

         注册事件:将事件处理方法连接到发行者事件上,如前面热水器示所示,将显示水温方法添加到发行者事件上,添加事件时使用“+=”操作符,同样也可使用“-=”撤销事件上的方法。只有当事件引用为空,才会回收其内存变量。

         触发事件:调用事件时触发事件。如热水器示所示,调用烧水方法时,进而调用了事件,则触发了事件,进而执行了相应的事件处理方法。

         事件存取器:在大多数情况下,是不需要定义事件存取器,因为编译器会自动添加事件访问器。但当每个事件的开销太大时,则需要声明事件存取器,包含 add 和 remove 两种存取器。因为类为每一个事件都声明一个字段,而事件又是引用类型,则需要在堆中开辟空间以存储事件对象,由此便造成资源的浪费。

2   常见事件应用类型

2.1  符合 .NETFramework 准则的事件

2.2  派生类中引发基类事件

 

2.3  实现接口事件

3   参考

C# 自学手册

C# 编程指南

.Net 之美


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值