定义一个类型来监听事件
public sealed class Fax
{
public Fax(MailManager mm)
{
// 注册回调方法FaxMsg
mm.NewMail += FaxMsg;
}
// 当NewEmail发生时,触发这个方法执行
private void FaxMsg(Object sender, NewMailEventArgs e)
{
// 'sender'用来识别是MailManager对象
// 'e' MailManager要传递的额外的事件信息
Console.WriteLine("Faxing mail message:");
Console.WriteLine(" From={0}, To={1}, Subject={2}",
e.From, e.To, e.Subject);
}
//从事件从注销方法,以后不在收到通知
public void Unregister(MailManager mm)
{
mm.NewMail -= FaxMsg;
}
}
C#内置对事件的支持,编译会根据+=生成代码:mm.add_NewMail(new EventHandler<NewMailEventArgs>(this.FaxMsg));
编译器构造了一个EventHandler<NewMailEventsArgs>委托对象来封装Fax类的FaxMsg方法。然后,C#编译器调用MailManager的add_NewMail方法,将它传递到新的委托。IL如下:
.event class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> NewMail
{
.addon instance void TypeTest.MailManager::add_NewMail(class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs>)
{
.locals init (
[0] class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> V_0,
[1] class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> V_1,
[2] class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> V_2,
[3] bool V_3
)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> TypeTest.MailManager::NewMail
IL_0006: stloc.0
.loop
{
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
IL_0010: castclass class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs>
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> TypeTest.MailManager::NewMail
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs>>(!!0&, !!0, !!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: ceq
IL_0028: ldc.i4.0
IL_0029: ceq
IL_002b: stloc.3
IL_002c: ldloc.3
IL_002d: brtrue.s IL_0007
}
IL_002f: ret
}
.removeon instance void TypeTest.MailManager::remove_NewMail(class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs>)
{
.locals init (
[0] class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> V_0,
[1] class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> V_1,
[2] class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> V_2,
[3] bool V_3
)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> TypeTest.MailManager::NewMail
IL_0006: stloc.0
.loop
{
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: ldarg.1
IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
IL_0010: castclass class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs>
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> TypeTest.MailManager::NewMail
IL_001c: ldloc.2
IL_001d: ldloc.1
IL_001e: call class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs> [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler`1<class TypeTest.NewMailEventArgs>>(!!0&, !!0, !!0)
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: ceq
IL_0028: ldc.i4.0
IL_0029: ceq
IL_002b: stloc.3
IL_002c: ldloc.3
IL_002d: brtrue.s IL_0007
}
IL_002f: ret
}
}
当MailManager对象触发了事件,Fax对象的FaxMsg方法会被调用,这个方法的一个引用会被作为MailManager对象的第一个参数sender传递给MailManager。多数时候该参数被忽略。当Fax对象想访问MailManager对象来响应事件通知时会使用。第二个参数是NewMailEventArgs对象,传递额外的信息。
当一个对象不再希望接收某事件的通知时,应该从事件里面注销。只要某一个对象的任何一个方法还在事件里面,这个对象就不会被GC回收。如果类型实现了IDisposable的Dispose方法,该实现应该注销所有在事件里面的方法。
本文导航
- 第1页: 首页
- 第2页: 编译器是怎么实现事件的?
- 第3页: 定义类型监听事件