歡迎您光臨本站 註冊首頁

詳解C#之事件

←手機掃碼閱讀     ml5rwbikls @ 2020-06-10 , reply:0

事件:定義了事件成員的類允許通知其他其他物件發生了特定的事情。具體的說,定義了事件成員的類能提供以下功能

1.方法能登記它對事件的關注

2.方法能登出它對事件的關注

3.事件發生時,登記了的方法將收到通知

型別之所以能提供事件通知功能,是因為型別維護了一個已登記方法的列表。事件發生後,型別將通知列表中所有已登記的方法。

事件是以委託為基礎。委託是呼叫回撥方法的一種型別安全的方式。物件憑藉回撥方法接收他們訂閱的通知。

假如有一下場景:要設計一個電子郵件程式。當有新的郵件的到達時,使用者希望做些一別的操作,例如轉發給其他人或其他想實現的功能。事件在其中起到的就是一個通知的作用,告訴其他物件有新的郵件到達了,可以做XXX事情了。

下面使用事件實現這個功能

1.定義一個附加資訊類,用來通知接收者發生了什麼。

  ////// 事件附加訊息    ///public 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;}}    }

 

附加資訊類繼承了EventArgs,這個基類只定義了一個空的資訊,在沒有附加資訊時可直接使用EventArgs.Empty。EventArgs類的原始碼

  namespace System  {    //    // Summary:    //   Represents the base class for classes that contain event data, and provides a    //   value to use for events that do not include event data.    public class EventArgs    {      //      // Summary:      //   Provides a value to use with events that do not have event data.      public static readonly EventArgs Empty;        //      // Summary:      //   Initializes a new instance of the System.EventArgs class.      public EventArgs();    }  }

 

2.定義事件成員

事件成員使用C#關鍵字event定義。每個事件成員都要指定以下內容:可訪問識別符號public(因為只有publi才能使其他物件訪問),委託型別以及名稱。

   public class MailManager{      // 定義事件成員      public event EventHandlerNewMail;          }

 

它的型別是EventHandler這意味著事件通知的所有接收者都必須有一個和這個型別匹配的回撥方法。System.EventHandler的委託定義型別如下:

  namespace System  {    //    // Summary:    //   Represents the method that will handle an event when the event provides data.    //    // Parameters:    //  sender:    //   The source of the event.    //    //  e:    //   An object that contains the event data.    //    // Type parameters:    //  TEventArgs:    //   The type of the event data generated by the event.    public delegate void EventHandler(object sender, TEventArgs e);  }

 

所以接收者必須提供的方法必須是一下形式:

void MethodName(Object sender,NewMailEventArgs e);

3. 定義負責引發事件的方法來通知事件的登記物件

  public class MailManager{      // 定義事件成員      public event EventHandlerNewMail;      // 定義負責引發事件的方法來通知已登記的物件      protected virtual void OnNewMail(NewMailEventArgs e){        // 將欄位複製到一個臨時變數,避免多執行緒情況中這個成員被移除        EventHandlertemp=Volatile.Read(ref NewMail);        if(temp!=null) temp(this,e);      }        // 接受附加資訊並呼叫引發事件的方法來通知所有登記的物件      public void SimulateNewMail(string from,string to,string subject){        NewMailEventArgs e=new NewMailEventArgs(from,to,subject);        OnNewMail(e);      }    }

 

4. 定義事件接收者

  public class Fax{      public Fax(MailManager mm){        // 構造委託例項,向事件登記回撥方法        mm.NewMail+=FaxMsg;      }      ////// 回撥方法      //////表示MailManager物件,便於將資訊傳遞給他///表示MailManager物件想傳給我們的附加資訊private void FaxMsg(object sender,NewMailEventArgs e){        Console.WriteLine("msg:{0},{1},{2}",e.From,e.To,e.Subject);      }        ////// 登出對事件的登記      //////public void Unregister(MailManager mm){        mm.NewMail-=FaxMsg;      }    }

 

物件不在接收事件通知時應登出對事件的關注。因為物件只要向事件等急了它的一個方法,便不能被垃圾回收。

5. 程式初始化時應首先構造MailManager物件,將指向它的變數傳遞給Fax。在Fax構造器中新增對事件的關注。最後呼叫MailManager物件的事件通知方法

  static void Main(string[] args)      {        MailManager mm=new MailManager();        Fax f=new Fax(mm);        mm.SimulateNewMail("a","b","Hello World!");        Console.ReadKey();      }

 

控制檯輸出結果:以呼叫回撥方法。

                    


[ml5rwbikls ] 詳解C#之事件已經有354次圍觀

http://coctec.com/docs/vscode/show-post-237914.html