1. 程式人生 > >通俗易懂地解釋一下C#中的事件和委託

通俗易懂地解釋一下C#中的事件和委託

如果你用過C/C++ 的函式指標,那麼跟你說委託就是函式指標,事件就是儲存多個函式指標的陣列就夠了。
否則就舉栗子吧。
----------開始嘮叨的分割線-----------
如何使用委託?
//第1步,申明,並說明該委託的簽名(即引數個數,型別)
public delegate int SomeDelegate(string s, bool b);
//第2步,定義符合委託簽名(即引數個數與型別一致)的函式。
private int SomeFunction(string s, bool b){...}
//第3步,建立一個委託,把函式名作為引數傳遞給該委託的建構函式。
SomeDelegate sd = new SomeDelegate(SomeFunction);
//第4步,使用該委託的例項呼叫該例項函式。
sd("somestring", true);
為什麼要這麼麻煩?本來可以直接 SomeFunction("somestring", true); 一步搞定的,你現在搞了四步?
:函式引數不允許傳遞函式。有了委託,你就可以把函式當成引數變數一樣傳遞了。
把函式當成引數變數一樣傳遞有什麼好處?
:可以傳遞函式意味著可以將業務邏輯作為引數傳遞,能極大的提高函式的通用性。
---------------------
如何使用事件?
//第1步,申明一個委託
public delegate int SomeDelegate(string s, bool b);
//第2步,定義符合委託簽名(即引數個數與型別一致)的函式。
private int SomeFunction(string s, bool b){...}
//--前2步都相同
//第3步,申明一個的事件,並定義該事件能接受的簽名。
public event SomeDelegate SomethingHappened;
//第4步,通過事件來儲存符合簽名的函式(可以是多個)
myObj.SomethingHappened += new SomeDelegate(SomeFunction);
//第5步,根據需要在適當的時機,執行事件中儲存的函式
  if( SomethingHappened != null ) {
      foreach( SomeDelegate sd in SomethingHappened.GetInvocationList() ) {
        int result = sd("somestring", true);
      }
    }
為什麼需要事件?
事件最常用的應用場景是圖形使用者介面(GUI),如WinForm和WebForm,需要程式來對事件作出響應。可以是一個按鈕點選事件,選單選擇事件,檔案傳輸完成事件等。簡單的說,某件事發生了,你必須要作出響應。你不能預測事件發生的順序。只能等事件發生,再作出相應的動作來處理。
在GUI環境裡面,所有的控制元件都能觸發事件,如你點選按鈕,觸發點選(Click)事件,你在下拉列表中增加了專案,出發了列表改動(ListChanged)事件。
其他的類會對響應這些事件感興趣。觸發事件的類本身對怎樣處理事件不感興趣。按鈕說:“我被點過了”,響應類(如Form或Page)作出合適的響應。
釋出和訂閱
所有的物件都能釋出一系列事件供其他類訂閱。當釋出物件觸發事件的時候,所有訂閱的類都會被通知到。有了這種機制,你的物件可以說,“我要告訴你們一些事情”,其他的類會說“好的,告訴我們發生什麼了”。比如,一個按鈕被點選的時候會通知那些感興趣的觀察者。按鈕稱為釋出者,因為按鈕釋出了點選事件。其他類是訂閱者,因為它們訂閱了點選事件。注意釋出類不需要知道或關係誰訂閱了;它只管觸發事件。誰響應了事件,怎麼響應的,釋出類都不關心。
為什麼更麻煩了?
:因為事件中儲存了一個符合委託簽名的函式列表。使得業務邏輯的傳遞更靈活了。
我使用事件沒有你說的這麼麻煩?
:因為微軟設計WinForm或者WebForm時已經把第1,3,4,5步都放在釋出類中做過了。我們只需要在訂閱類中做第2步就行了,自然簡單。

推薦看:Events and Delegates Simplified Chapter 17. Delegates and Events,我就是一個搬運工。