定義一個(gè)類型來監(jiān)聽事件
public sealed class Fax
{
public Fax(MailManager mm)
{
// 注冊(cè)回調(diào)方法FaxMsg
mm.NewMail += FaxMsg;
}
// 當(dāng)NewEmail發(fā)生時(shí),觸發(fā)這個(gè)方法執(zhí)行
private void FaxMsg(Object sender, NewMailEventArgs e)
{
// 'sender'用來識(shí)別是MailManager對(duì)象
// '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#內(nèi)置對(duì)事件的支持,編譯會(huì)根據(jù)+=生成代碼:mm.add_NewMail(new EventHandler<NewMailEventArgs>(this.FaxMsg));
編譯器構(gòu)造了一個(gè)EventHandler<NewMailEventsArgs>委托對(duì)象來封裝Fax類的FaxMsg方法。然后,C#編譯器調(diào)用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
}
}
當(dāng)MailManager對(duì)象觸發(fā)了事件,F(xiàn)ax對(duì)象的FaxMsg方法會(huì)被調(diào)用,這個(gè)方法的一個(gè)引用會(huì)被作為MailManager對(duì)象的第一個(gè)參數(shù)sender傳遞給MailManager。多數(shù)時(shí)候該參數(shù)被忽略。當(dāng)Fax對(duì)象想訪問MailManager對(duì)象來響應(yīng)事件通知時(shí)會(huì)使用。第二個(gè)參數(shù)是NewMailEventArgs對(duì)象,傳遞額外的信息。
當(dāng)一個(gè)對(duì)象不再希望接收某事件的通知時(shí),應(yīng)該從事件里面注銷。只要某一個(gè)對(duì)象的任何一個(gè)方法還在事件里面,這個(gè)對(duì)象就不會(huì)被GC回收。如果類型實(shí)現(xiàn)了IDisposable的Dispose方法,該實(shí)現(xiàn)應(yīng)該注銷所有在事件里面的方法。
本文導(dǎo)航
- 第1頁: 首頁
- 第2頁: 編譯器是怎么實(shí)現(xiàn)事件的?
- 第3頁: 定義類型監(jiān)聽事件