在上一篇中
public event MailMsgEventHandler MailMsg;
C#编译器会将这段代码翻译为3个构造:
代码
//
1,一个被初始化为null的“私有”委托字段类型
private MailMsgEventHandler MailMsg = null ;
// 2,一个允许对象登记事件的“公有”add _*方法
public void add_MailMsg(MailMsgEventHandler handler)
{
MailMsg = (MailMsgEventHandler)Delegate.Combine(MailMsg,handler);
}
// 3一个允许对象注销事件的“公有”remove_*方法;
public void remove_MailMsg(MailMsgEventHandler handler)
{
MailMsg = (MailMsgEventHandler)Delegate.Remove(MailMsg,handler);
}
private MailMsgEventHandler MailMsg = null ;
// 2,一个允许对象登记事件的“公有”add _*方法
public void add_MailMsg(MailMsgEventHandler handler)
{
MailMsg = (MailMsgEventHandler)Delegate.Combine(MailMsg,handler);
}
// 3一个允许对象注销事件的“公有”remove_*方法;
public void remove_MailMsg(MailMsgEventHandler handler)
{
MailMsg = (MailMsgEventHandler)Delegate.Remove(MailMsg,handler);
}
Fax的注册事件的代码:
mm.MailMsg += new MailManager.MailMsgEventHandler(FaxMsg);
因为C#编译器对事件提供了内在的支持,所以上面一行将转换为下面的代码:
mm.add_MailMsg( new MailManager.MailMsgEventHandler(FaxMsg));
注销事件代码可以转换为:
mm.remove_MailMsg( new MailManager.MailMsgEventHandler(FaxMsg));
C#要求我们使用+=和-+来在委托莲上面添加和移除事件,而不允许显示调用add和remove方法,如果我们感觉编译器自动产生的add和remove方法不够理想,我们可以显示实现add和remove方法,下面实例对前面的MailManager类型进行了修改,为add和remove访问器提供了显示的实现;
代码
public
class
MailManagerB
{
public MailManagerB()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/// <summary>
/// 定义事件信息的类型,事件的附件信息
/// </summary>
public class MailMsgEventArgs : EventArgs
{
public MailMsgEventArgs( string from, string to, string subject, string body)
{
this .from = from;
this .to = to;
this .subject = subject;
this .body = body;
}
public readonly string from, to, subject, body;
}
// 委托类型定义了接收者必须实现的回调方法原型
public delegate void MailMsgEventHandler( object sender, MailMsgEventArgs args);
// 显式定义一个私有委托链表字段
private MailMsgEventHandler mailMsgEventHandlerDelegate;
// 显式定义事件及其访问器方法
public event MailMsgEventHandler MailMsg
{
add
{
// 将传入的事件处理器(value)添加到委托链表上
mailMsgEventHandlerDelegate = (MailMsgEventHandler)Delegate.Combine(mailMsgEventHandlerDelegate, value);
}
remove
{
// 将传入的事件处理器(value)从委托链表上移除
mailMsgEventHandlerDelegate = (MailMsgEventHandler)Delegate.Remove(mailMsgEventHandlerDelegate, value);
}
}
/// <summary>
/// 负责通知事件的登记对象
/// </summary>
/// <param name="e"></param>
protected virtual void OnMailMsg(MailMsgEventArgs e)
{
// 有对象登记事件吗?
if (mailMsgEventHandlerDelegate != null )
{
// 如果有,则通知委托链表上的所有对象
mailMsgEventHandlerDelegate( this , e);
}
}
public void SimulateArrivingMsg( string from, string to, string subject, string body)
{
// 构造一个对象保存希望传递给通知者的信息
MailMsgEventArgs e = new MailMsgEventArgs(from, to, subject, body);
OnMailMsg(e);
}
}
{
public MailManagerB()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/// <summary>
/// 定义事件信息的类型,事件的附件信息
/// </summary>
public class MailMsgEventArgs : EventArgs
{
public MailMsgEventArgs( string from, string to, string subject, string body)
{
this .from = from;
this .to = to;
this .subject = subject;
this .body = body;
}
public readonly string from, to, subject, body;
}
// 委托类型定义了接收者必须实现的回调方法原型
public delegate void MailMsgEventHandler( object sender, MailMsgEventArgs args);
// 显式定义一个私有委托链表字段
private MailMsgEventHandler mailMsgEventHandlerDelegate;
// 显式定义事件及其访问器方法
public event MailMsgEventHandler MailMsg
{
add
{
// 将传入的事件处理器(value)添加到委托链表上
mailMsgEventHandlerDelegate = (MailMsgEventHandler)Delegate.Combine(mailMsgEventHandlerDelegate, value);
}
remove
{
// 将传入的事件处理器(value)从委托链表上移除
mailMsgEventHandlerDelegate = (MailMsgEventHandler)Delegate.Remove(mailMsgEventHandlerDelegate, value);
}
}
/// <summary>
/// 负责通知事件的登记对象
/// </summary>
/// <param name="e"></param>
protected virtual void OnMailMsg(MailMsgEventArgs e)
{
// 有对象登记事件吗?
if (mailMsgEventHandlerDelegate != null )
{
// 如果有,则通知委托链表上的所有对象
mailMsgEventHandlerDelegate( this , e);
}
}
public void SimulateArrivingMsg( string from, string to, string subject, string body)
{
// 构造一个对象保存希望传递给通知者的信息
MailMsgEventArgs e = new MailMsgEventArgs(from, to, subject, body);
OnMailMsg(e);
}
}
以上代码便是显示控制事件的注册:
- 显式定义一个私有委托链表字段,在上一篇中,虽然我们定义的委托为公有字段,但是编译器自动会将其编译为private,为什么呢,将委托字段定义为私有方式可以防止类型外的代码错误的操作该字段,如果该字段设为public,那么任何代码都可以为其赋值,从而会删除所有已登记事件的委托实例;
- 显式定义事件及其访问器方法,每一个访问器方法都接受一个类型为MailMsgEventHandler的隐含参数(value)。这些方法在内部或者向委托链表上添加或者移除一个MailMsgEventHandler实例,,我们知道属性可以拥有get和set访问器方法,或者拥有其中之一,但是事件必须同时拥有add和remove。
- 定义一个受保护的虚方法,负责通知事件的登记对象,和上一篇不同的是这次将事件的名字换成了委托哦名字