[什么是事件]
—在C和C++程序中,常为事件通知使用回调函数和函数指针。
—C#使用一个称为event的特殊委托类型向客户端提供事件通知。
—C#中的事件只能在声明这个事件的类中引发
—so事件基于委托:属于类型安全,(约定声明事件处理常用EventHandler作为名字结尾,而在类中引发的事件被命名为OnEventName)
[为什么事件基于委托]
在事件通信中,事件发送方类不知道哪个对象或方法将接收到(处理)它引发的事件。所需要的是在源和接收方之间存在一个媒介(或类似指针的机制)。.NET Framework 定义了一个特殊的类型(Delegate),该类型提供函数指针的功能。
委托是一个可以对方法进行引用的类。与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用。这样,委托就等效于一个类型安全函数指针或一个回调。虽然委托具有许多其他的用途,但这里只讨论委托的事件处理功能。下面的示例显示了事件委托声明。
[C#]
// AlarmEventHandler is the delegate for the Alarm event.
// AlarmEventArgs is the class that holds event data for the alarm event.
// It derives from the base class for event data, EventArgs.
public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
该语法与方法声明的语法相似,但是 delegate 关键字通知编译器 AlarmEventHandler
是一个委托类型。按照约定,.NET Framework 中的事件委托有两个参数:引发事件的源和该事件的数据。
注意 一个委托声明足以定义一个委托类。声明提供委托的签名,公共语言运行库提供实现。AlarmEventHandler 委托的实例可以绑定到任何一个与其签名匹配的方法上,例如下面的示例中显示的 WakeMeUp 类的 OnAlarmRang 方法。
[C#]
public class WakeMeUp
{
// AlarmRang has the same signature as AlarmEventHandler.
public void OnAlarmRang(object sender, AlarmEventArgs e){...};
...
}
[如何引发一个事件]
事件功能是由三个互相联系的元素提供的:提供事件数据的类、事件委托和引发事件的类。.NET Framework 具有命名与事件相关的类和方法的约定。如果想要您的类引发一个名为 EventName 的事件,您需要以下元素。
l 持有事件数据的类,名为 EventNameEventArgs。该类必须从 System.EventArgs 导出。
l 事件的委托,名为 EventNameEventHandler。
l 引发事件的类。Step如下
[C#]
public class AlarmEventArgs : EventArgs ... {
private readonly bool snoozePressed = false;
private readonly int nrings = 0;
// Constructor.
public AlarmEventArgs(bool snoozePressed, int nrings) ...{...}
// Properties.
public int NumRings...{ get ...{ return nrings;}}
public bool SnoozePressed ...{ get ...{ return snoozePressed;}}
public string AlarmText ...{ get ...{...}}
}
// Step 2. Delegate declaration. 定义事件的委托
public delegate void AlarmEventHandler( object sender, AlarmEventArgs e);
// Class definition. 定义一个拥有触发事件的类
//
public class AlarmClock
... {
//Step 3. The Alarm event is defined using the event keyword. The type of Alarm is AlarmEventHandler.
// 使用 event 关键字(其类型是事件委托)在您的类中定义一个公共事件成员。
public event AlarmEventHandler Alarm;
//Step 4. The protected OnAlarm method raises the event by invoking the delegates.
//The sender is always this, the current instance of the class.
// 用于触发事件的OnAlarm方法
protected virtual void OnAlarm(AlarmEventArgs e)
...{
if (Alarm != null)
...{
//Invokes the delegates.事件远源this类,e为第一步建立的AlarmEventArgs 类
Alarm(this, e);
}
}
public void Start()
...{
...........
//在适当的时候,触发OnAlame即可
OnAlarm(e);
...........
}
//用户可以通过调用该以下方法增加事件,取消事件
public void AddOnAlarm(AlarmEventHandler handler)
...{
AlarmEventHandler += handler;
}
public void RemoveOnAlarm(OverdraftEventHandler handler)
...{
AlarmEventHandler -= handler;
}
}
// Step5 Class definition. 定义主函数 // 不同于MSDN上的例子,改简单了,把WakeMeUp类定义为一个事件处理程序的目标,而之前的版本其实是WakeMeUp的一个方法
//
public class AlarmDriver
... {
public static void Main (string[] args)
...{
// Instantiates the event source.
AlarmClock clock = new AlarmClock();
// Wires the OnWakeMeUp method to the Alarm event.
//OnWakeMeUp即为上面AlarmClock类中触发事件的目标—事件发生就会激发这个处理方法
clock. AddOnAlarm(OnWakeMeUp);
clock.start();
}
static void OnWakeMeUp (object sender,AlarmEventArgse)
...{
//这样就可以处理事件,调用事件传过来的数据 e 了
}
}