C#事件
事件是C#中很重要的一个特点,我们可以把ASP.NET和WinForm开发看成是基于事件驱动的开发,即系统会捕捉我们的操作,例如单击一个Button,这时会触发一段特定的代码,执行相应的逻辑。
C#事件充分利用了委托的强大功能,一个典型的事件代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
执行EventTest的Test方法,执行结果为:
The result is 6
上面的代码和我们平时使用事件时看到的代码不太一样,.NET Framework为了规范事件的实现方式,提供了一组形式比较严谨的类,主要包括EventHandler类和EventArgs类。
一个符合.NET Framework规范的事件,代码如下
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
一个事件中需要包含两个参数,一个是触发事件的对象,一般成为sender,一个是事件参数EventArgs,我们可以根据业务的需要,对EventArgs类进行扩充,例如上面代码中的CustomEventArgs。
当我们定义好事件参数后,可以利用EventHandler来定义一个事件,在.NET Framework 2.0后,添加了泛型,可以使用EventHandler<T> 的形式来声明一个事件,其中T表示声明的事件所需的事件参数,例如上面代码中的EventHandler<CustomEventArgs>。
我们应该弄清楚的一个概念就是事件应该是有发布者和订阅者两类角色,关于这方面,请参考博客园另外两篇针对委托和事件非常不错的文章:C# 中的委托和事件和C#中的委托和事件(续),对委托和事件都进行了深入浅出的讲解。
其实看到上面的代码,我就想起了设计模式中的模板模式,从另外一个角度看,我们可以把事件发布者看做一个抽象类,声明的事件作为抽象方法,事件的订阅者看做是继承自抽象类的各个子类,这样它们必须实现抽象方法。通过调用子类调用父类中的方法,也可以实现事件带来的功能。但是在这种情况下,不推荐使用模板,主要原因是我们要明确触发事件的对象到底应该是谁?作为事件的订阅者,它可以知道事件发布者中的其他方法吗?显然是不应该,所以我们在这种情况下,不应该使用模板模式。
另外一个和继承相关的话题就是子类调用父类的事件。关于事件,有如下规则:事件是特殊类型的委托,只可以从声明它们的类中调用。派生类无法直接调用基类中声明的事件。那么如何解决这个问题呢?我们可以在父类中将调用事件的方法设置为protected virtual,这样子类就可以复写父类的方法,在子类复写的方法体内,直接调用父类的方法。通过这种方式,我们可以实现子类调用父类中的事件。