您的位置:首页 > 编程语言 > C#

C#事件-探寻事件本质

2012-06-28 07:36 801 查看
如何定义一个事件?

语法:访问修饰符 event关键字 委托类名 事件名;

比如:public event somedelegatename myeventname;

事件到底是什么类型(引用?值?)

事件其实就是一个特殊的委托。

MSDN中的C#参考里这样描述:事件是特殊类型的多路广播委托,仅可从声明它们的类或结构(发行者类)中调用。如果其他类或结构订阅了该事件,则当发行者类引发该事件时,会调用其事件处理程序方法。

对于这一点,我们也可以从事件的定义中看出,不过就是在定义委托对象时加了event关键字表明这个委托现在叫事件。

何谓事件的订阅(subscribe)?

我们用VS建立一个只有一个按钮的winform程序,双击按钮,设计器会在Form1.Designer.cs中自动生成一行代码

this.button1.Click += new System.EventHandler(this.button1_Click);

这就是事件的订阅!其实就是用事件处理函数this.button1_Click来实例化一个委托System.EventHandler(这个函数与委托拥有同样的签名),并把这个委托对象赋给事件Click(因这Click其实就是一个委托引用,所以可以这样做)

一句话,订阅事件就是将某个委托对象指向一个具体的方法。

什么是引发事件?

当程序中满足某个条件时调用事件就是引发了事件,为什么可以调用事件呢?因为事件就是一个委托,调用委托就是调用委托中封装的事件处理函数。

为什么事件可以被多个对象订阅?

知道了事件实际是一个多播委托后,这个问题不难理解,所谓被多个对象订阅,就是事件被触发后,可以导致多个对象做出反应,也就是多个对象的某个事件处理函数被调用。为什么会这样呢,因为事件是多播委托,即封装了多个函数的委托,调用这个委托实际上就是在调用被封装的这多个函数。

下面用一个最简单的控制台程序例子来说明事件的运作方式

using System;
namespace 最简单的自定义事件
{
/// <summary>
/// 事件发送类,即调用事件的类
/// </summary>
class Class1
{
public delegate void mydelegate(object sender,EventArgs e); //定义委托
public event mydelegate myevent; //定义一个委托类型的事件,即定义一个委托对象

public void run()
{
//死循环,不停测试某个条件是否满足,即所谓的监听
while(true)
{
if(Console.ReadLine()=="a")
{
myevent(this,new EventArgs()); //调用事件
}
}
}
}

/// <summary>
/// 事件接收类,即事件处理的类
/// </summary>
class Class2
{
static void Main(string[] args)
{
Class1 c1 = new Class1();
c1.myevent+= new Class1.mydelegate(c1_myevent); //将委托对象指向具体的事件处理函数,即所谓的订阅事件
c1.run();//运行这个事件,因为此时委托已经指向了具体方法,可以运行了
}

private static void c1_myevent(object sender, EventArgs e)
{//事件处理方法
Console.WriteLine(" 你触发了事件!");
}
}
}
对于这个例子,为了加深理解事件的本质,我们可以把事件订阅c1.myevent+= new Class1.mydelegate(c1_myevent); 这句注释掉,即事件没有指向任何具体的方法,编译,不会报错,运行它,如果我们不输入
字符串“a”,程序仍然运行正常,因为这时没有满足事件触发条件,一旦输入a回车,就会报如下错误:

未处理的异常:System.NullReferenceException未将对象引用设置到对象实例。

很显然,就是相当于我们调用了一个没有指向任何函数的函数指针。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: