第 11 章 事 件 发表于 2026-01-03 更新于 2026-01-03
第 11 章 事 件 本章内容:
11.1.1 第一步:定义类型来容纳所有需要发送给事件通知接收者的附加信息 11.1.2 第二步:定义事件成员 11.1.3 第三步:定义负责引发事件的方法来通知事件的登记对象 11.1.4 第四步:定义方法将输入转化为期望事件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 using System;using System.Threading;namespace ch11 { internal class NewMailEventArgs : EventArgs { private readonly String m_from, m_to, m_subject; public NewMailEventArgs (String from , String to, String subject ) { m_from = from ; m_to = to; m_subject = subject; } public String From { get { return m_from; } } public String To { get { return m_to; } } public String Subject { get { return m_subject; } } } internal class MailManager { public event EventHandler<NewMailEventArgs> NewMail; protected virtual void OnNewMail (NewMailEventArgs e ) { EventHandler<NewMailEventArgs> temp = Volatile.Read(ref NewMail); if (temp != null ) temp(this , e); } public void SimulateNewNail (String from , String to, String subject ) { NewMailEventArgs e = new NewMailEventArgs(from , to, subject); OnNewMail(e); } } public static class EventArgsExtensions { public static void Raise <TEventArgs >(this TEventArgs e, Object sender, ref EventHandler<TEventArgs> eventDelegate ) { EventHandler<TEventArgs> temp = Volatile.Read(ref eventDelegate); if (temp != null ) temp(sender, e); } } }
MailManager类用一行代码定义了事件成员本身:public event EventHandler<NewMailEventArgs> NewMail;
C# 编译器编译时把它转换为以下 3 个构造:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private EventHandler<NewMailEventArgs> NewMail = null ;public void add_NewMail (EventHandler<NewMailEventArgs> value ) { EventHandler<NewMailEventArgs> preHandler; EventHandler<NewMailEventArgs> newMail = this .NewMail; do { preHandler = newMail; EventHandler<NewMailEventArgs> newMail = (EventHandler<NewMailEventArgs>) Delegate.Combine(preHandler, value ); newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(ref this .NewMail, newHandler, preHandler); } while (newMail != preHandler); } public void remove_NewMail (EventHandler<NewMailEventArgs> value ) { EventHandler<NewMailEventArgs> preHandler; EventHandler<NewMailEventArgs> newMail = this .NewMail; do { preHandler = newMail; EventHandler<NewMailEventArgs> newHandler = (EventHandler<NewMailEventArgs>) Delegate.Remove(preHandler, value ); newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(ref this .NewMail, newHandler, preHandler); } while (newMail != preHandler); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 internal sealed class Fax { public Fax (MailManager mm ) { mm.NewMail += FaxMsg; } private void FaxMsg (Object sender, NewMailEventArgs e ) { 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; } }
通过显式实现事件,开发人员可以控制add和remove方法处理回调委托的方式,以高效地处理大量事件。为了存储事件委托,每个对象都维护一个集合,使用事件标识符作为键,委托列表作为值。当对象需要触发事件时,将调用与标识符关联的委托列表。具体实现方式由定义事件的类型的开发人员决定。