首 页 华育简介 就业解决方案 课程师资 高端合作 就业明星 在线报名 华育人专区
选择华育,选择生活
 
 
 
技术交流区 首页 - 华育新闻 - 关于华育


C#深入剖析(1)——事件

  事件相信每个人都不陌生,随便一个WinForm程序,就会使用大量的事件,比如:

C# code
class MainForm : Form
{
public MainForm()
{
this.Click += new EventHandler(MainForm_Click);
}
private void MainForm_Click(object sender, EventArgs e)
{
}
}

  当然,还可以对代码进行简化,如类型的自动推断,匿名方法,Lambda表达式等。这个事件大概的工作流程为:当用户单击窗体时,操作系统向应用程序发送一系列消息,如左键按下和左键抬起,应用程序将通过GetMessage等方法最终将消息提交到窗口过程(WndProc),窗口过程通过处理消息,当发现产生了连续的左键按下和左键抬起的消息后, 就知道产生了单击事件,于是去调用窗体的OnClick方法,该方法会去检测一下是否订阅了Click事件,如果订阅了,就会去调用相应的事件处理程序,这个过程是通过委托实现的。

  下面我从语法角度来分析一下事件:

  事件是类、结构或接口中的一个成员,它有两种定义形式:
一、
C# code
event MethodInvoker OneEvent;

二、

C# code
event MethodInvoker OneEvent
{
add
{
}
remove
{
}
}
其中MethodInvoker

  是一个没有参数和返回值的委托,它只是用来约束事件处理程序的的形式,你可以任意定义一个,例如你可以使用Action来代替。 事件包括两个访问器,其中add访问器会在订阅事件时触发,remove访问器在取消事件订阅时触发。 对于第一种定义形式,系统会自动提供add及remove访问器,同时会提供如下字段:
C# code
private MethodInvoker OneEvnet;

  该字段的类型为委托的类型,字段名跟事件名相同(一个类中拥有同名成员,C#编译器是不允许的,但是系统可以)。
C# code

class Demo
{
public void InvokeEvent()
{
if (OneEvent != null)
OneEvent();//调用事件
if (TwoEvent != null)
{
string str = TwoEvent(217);//调用事件
MessageBox.Show(str);
}
}
public event MethodInvoker OneEvent;
public event Func<int, string> TwoEvent;
}
private void button1_Click(object sender, EventArgs e)
{
Demo de = new Demo();
de.OneEvent += delegate
{
MessageBox.Show("事件被调用");
};
de.TwoEvent += arg => arg.ToString();
de.InvokeEvent();
}

  可以看出,这里事件类似于方法和委托,可以传递参数并被调用。事实上,这只是编译器的一种包装,这里其实使用的正是前面提到的同名的委托字段。而如果是在一个类中访问另一个类中的事件,或者如下面将要提到的自己提供访问器的情况,由于不存在同名的委托字段,事件就不能再这样使用了,而只能出现在+=和-=运算符的左侧。

  至少有两个理由使得我们需要自己提供访问器:
1. 希望在订阅或取消事件时执行一段代码。
2. 前面提到,如果不提供访问器,每定义一个事件,系统就会生成一个同名的委托字段,如果事件特别多,这就是一项巨大的开销,而如果定义了访问器,则不再提供,此时我们可以用一种统一的方式来处理,从而节省资源,实际上,WinForm就是这样处理的。
C# code
class Demo
{
public void InvokeEvent()
{
if(ehl[oneEvent]!=null)
ehl[oneEvent].DynamicInvoke();//调用事件
if (ehl[twoEvent] != null)
{
string str = ehl[twoEvent].DynamicInvoke(217) as string;//调用事件
MessageBox.Show(str);
}
}
EventHandlerList ehl = new EventHandlerList();
static readonly object oneEvent = new object();
static readonly object twoEvent = new object();
public event MethodInvoker OneEvent
{
//在add和remove访问器中,类似属性,存在一个value,表示要订阅和取消的委托

 
 
网站首页 | 在线咨询 | 在线报名 | 多方合作 | 联系方式 | 加入收藏 | 设为首页
Copyright 2009 华育国际西安软件实训基地 陕ICP备08006040号
联系电话:029-87208781 029-87208782 029-87208783
地址:西安市北大街新时代广场5层 710003
咨询QQ:1065173532 Http://www.xaeduask.com