目录
2.1Talk is cheap, show me the code.
1,什么是事件
1.1事件的定义
事件可以被认为是一种发生在对象上的通知,当特定的操作或条件发生时,它会通过委托将控制权传递给事件处理程序。委托是一个引用类型,它可以指向要执行的方法。可以使用+=运算符将委托添加到事件中,使用-=运算符将其从事件中移除。
事件处理程序是由程序员编写的代码块,它们指定了在事件发生时应执行的操作。当事件被触发时,事件处理程序将被调用,从而可以响应事件并执行相应的操作。
例如,一个按钮可以有Click事件。当用户单击该按钮时,Click事件将被触发,并且相关的事件处理程序将被调用。程序员可以编写事件处理程序来执行任何适当的操作,例如打开新窗口、更新数据、保存文件等等。
1.2事件和委托的区别
事件和委托是两种不同的概念。
委托是一种引用类型,它可以指向一个或多个方法,并且可以将委托作为参数或返回值进行传递。委托可以用于实现回调和异步编程等功能。委托是一种非常灵活和强大的机制,它是事件实现的基础。
事件是一种语言特性,是成员,它是基于委托实现的一种机制。事件通常用于响应用户操作、线程信号等等。事件的发布者在某个条件满足之后,会触发事件,然后通知所有订阅者执行相应的操作。事件实际上是一种安全的委托,它只允许订阅者添加或移除委托,但不允许修改委托列表。
因此,委托和事件是相互关联的两种概念。委托提供了一种方法执行的机制,而事件则是委托的一种应用,通过事件机制可以实现对象间的通信和协作。在实际编程中,委托和事件经常会一起使用,尤其是在GUI应用程序中,事件和回调函数是用户交互的基础。
1.3事件模型的5个组成部分
使用事件时的5个源代码组件
- 委托类型声明 事件和事件处理程序必须有共同的签名和返回类型,它们通过委托类型进行描述
- 事件处理程序声明 订阅者类中会在事件触发时执行的方法声明。他们不一定是显示命名的方法,还可以是匿名方法或者Lambda表达式
- 事件声明 发布者类必须声明一个订阅者类可以注册的事件成员。当类声明的事件为public时,称为发布了事件
- 事件注册 订阅者必须注册事件才能在事件被触发时得到通知。这是将事件处理程序与事件相连的代码
- 触发事件的代码 发布者类中“触发”事件并导致调用注册的所有事件处理程序的代码
注意:1,任何注册到事件(如注册)的处理程序都必须与委托类型的签名和返回值类型匹配
2,事件是类或结构的成员,不是类型,因此不能使用new表达式来创建它的对象
2,怎样使用事件
2.1Talk is cheap, show me the code.
直接看栗子:
delegate void Handler(); //声明委托,或者使用已有的委托类型
//发布者类
class Incrementer
{
public event Handler CountedADozen; //创建事件并发布
public void DoCount()
{
for (int i = 0; i < 10; i++)
{
if (i%3 ==0 && CountedADozen != null)
{
CountedADozen(); //每增加3个计数触发事件一次
}
}
}
}
//订阅者类
class Dozens
{
public int DozensCount { get; set; }
public Dozens(Incrementer incrementer)
{
DozensCount = 0;
//订阅事件(这里是订阅事件的简略通用的写法,订阅事件也可以用Lambda表达式赋值)
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);
}
}
注意:1,事件封装委托,使程序更安全,更有逻辑
2,这里的订阅语句其实是简略后的语法糖衣,在简化后的语法糖下,完全可以当事件是一个委托字段,把它当委托用,虽然这种理解是错的,但是理解使用起来更方便,更容易接受
2.2 EventHandler 委托类型,标准事件的用法
因为事件的广泛使用,.NET框架提供了一个标准模式。该标准模式的基础就是System命名空间中声明的EventHandler委托类型,这是个定义好的专门用于定义事件的通用委托
以下是EventHandler委托类型的声明:
public delegate void EventHandler(object sender, EventArgs e);
将上面的程序改为使用系统定义的EventHandler委托之后,代码如下:
//发布者类
class Incrementer
{
public event EventHandler CountedADozen; //使用EventHandler委托创建事件并发布
public void DoCount()
{
for (int i = 0; i < 10; i++)
{
if (i%3 ==0 &&CountedADozen != null)
{
CountedADozen(this,null); //触发事件时使用EventHandler的参数
}
}
}
}
//订阅者类
class Dozens
{
public int DozensCount { get; set; }
public Dozens(Incrementer incrementer)
{
DozensCount = 0;
incrementer.CountedADozen += IncrementDozensCount; //订阅事件
}
//事件处理程序的签名必须与委托的签名匹配
void IncrementDozensCount(object source,EventArgs e)
{
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);
}
}
其他:还可以自定义一个派生自EventArgs的类,新自定义类的委托类型,来使得可以向事件处理程序的第二个参数传递数据。
另外,一些刘铁猛老师的课程图片可供参考: