事件引入和本質

2021-09-22 16:56:52 字數 4404 閱讀 4821

用event 關鍵字使您可以宣告事件。

事件是類在相關事情發生時發出通知的方法。【簡述】事件就是類在發生其關注的事情的時候用來提供通知的一種方式。

要理解事件必須要先知道一下兩個角色:

事件發行者,也稱為傳送者(sender),說白了就是乙個物件,這個物件會自身維護本身的狀態資訊。當自身狀態資訊發生變動時,就觸發乙個事件,並通知所有事件的訂閱者

對事件感興趣的物件,也成為接受者(recevier),可以註冊你感興趣的事件,通常會其提供乙個事件處理程式,在事件發行者觸發乙個事件後,會自動觸發其**內容。

最經典的例子莫過於使用者向報社訂閱雜誌,下面就用一張圖來說明事件的流程。

報社有各種各樣的雜誌,當使用者想要檢視所需雜誌時,則必須首先得 訂閱

該雜誌,當報社 發行

了該雜誌時,則訂閱了雜誌的使用者就能收到該雜誌!所以這個例子中事件就是報社發行的雜誌事件,同時將該雜誌分發給已經訂閱該雜誌的使用者手中,從而形成了乙個完備的事件機制。下面我們就此例用**來進行實現。

1

public

class

publisher /*發行者*/212

}13}14

public

class

subscriber/*訂閱者*/

1520}21

class

program

2231 }

public

delegate

void publish(); 事件的**。  issue() 觸發事件的方法。 recieve() 訂閱者事件處理程式。控制台輸出入下:

通過這乙個例子想必我們對事件機制有了初步的認識。接下來為了更真實的理解事件機制,我們假設有如下情景:由於該報社混的不錯,在一小段時間內取得了不錯的業績,開始發行兩種雜誌,一種是雜誌,另一種是博問雜誌,鑑於此現將**進行改寫如下:

1

public

class

publisher214

}15public

void

issuecnblogsquestion()

1622}23

}24public

class

subscriber

2527

28public subscriber(string

name)

2932

public

void recieve(string

magezinename)

3336}37

class

program

3860

6162 }

看上述**報社發行了雜誌和博問雜誌,小紅只訂閱雜誌,小明訂閱了雜誌和博問雜誌,並通過 issuecnblogs  和 issuecnblogsquestion 方法來進行觸發發行這兩種雜誌,經過一段時間後,小明取消訂閱博問雜誌,最後小紅和小明收到的都是訂閱的雜誌。列印如下:

綜上所述我們得出定義乙個完整事件有四個步驟:

public

delegate

void eventnamehandler (object

sender, eventargs e)

public

event eventnamehandler eventname;

protected

virtual

void

oneventname (eventargs e)

}

下面就此規範對報社發行雜誌和訂閱者訂閱雜誌進行改造,如下:

1

public

class

pubeventargs : eventargs /*觸發事件的類pubeventargs*/210

public

string

magezinename

1113}14

15public

datetime magezinetime

1618}19

}20public

class

publisher /*發行者(報社即事件的發行者)*/

2134}35

public

virtual

void

onpubcnblogsquestion(pubeventargs e) /*提供乙個觸發發行博問雜誌事件的受保護的方法*/

3642}43

public

void issuecnblogs(string

magezine_name, datetime magezine_time) /*觸發發行雜誌的方法*/

4448

public

void issuecnblogsquestion(string

magezine_name, datetime magezine_time) /*觸發發行博問雜誌的方法*/

4953}54

public

class

subscriber /*訂閱者(使用者即事件的接受者)*/

5557

58public subscriber(string

name)

5962

public

void recieve(object

sender, pubeventargs e) /*訂閱者訂閱事件處理程式*/

6366}67

class

program

6893

9495 }

根據上述**列印出:

通過上述學習我們知道了事件和基本用法以及相關命名規範,下面我們一起來**事件本質。

通過上述我們寫的 publisher 發行者類,我們通過反編譯工具檢視其il**入下:

我們單拿發行者中的博問委託來看即可,我們上述在**中定義的委託變數是 public

event pubcnblogsquestioneventhandler pubcnblogsquestion; 但此時我們發現變數的訪問許可權變成了 private

私有的,同時該私有委託變數中新增了兩個方法 add 和 remove ,所以此時我們就得出這樣兩個結論,通過新增 event

關鍵字:(1)自動將委託變數變成了私有的(2)同時生成了add()和remove()兩個方法,也就說明事件中+=和-=是通過add()和remove()方法來實現的。

鑑於此我們看看add()方法到底是什麼東西?

add()內部實現最終是呼叫了委託的最終的父類的delegate中的combine方法來實現的,同時我們也能看到 this.pubcnblogsquestion ,通過上述我們知道用event關鍵字宣告的委託變數是私有的,那這個呼叫的pubcnblogsquestion變數是哪來的呢?不難看出通過event關鍵字宣告中其實就自動生成了委託變數同名的變數。還不信的話,請看下圖中的操作,會讓你深信不疑。  

當例項化發行者類後再對其委託變數pubcnblogsquestion進行賦值再編譯生成會通不過,上面也有說,此時你操作的是event關鍵字會自動生成與宣告的委託變數同名的乙個變數只能對其進行+=或者-=操作,而你宣告的委託變數是私有的,你是無法訪問的。通過這也驗證了這一觀點。

同理我們檢視其remove()方法的實現,想必你也能猜到,肯定也是操作委託中的最終父類delegate中的remove()方法對其進行-=操作。眼見為實:

委託依賴事件,何以見得呢?那麼 想想如果沒有事件會怎樣,想想當在實際專案中,上乙個程式設計師用到了委託,當該程式設計師捲鋪蓋走人,等到下乙個程式設計師來時不知道裡面到底實現了什麼或者說對其寫的委託實現進行了remove,那可怎麼辦!如果有了事件的話,你根本無法去操作委託物件,只能通過+=和-=來操作,這樣就避免了委託的濫用!

事件引入和本質

用event 關鍵字使您可以宣告事件。事件是類在相關事情發生時發出通知的方法。簡述 事件就是類在發生其關注的事情的時候用來提供通知的一種方式。要理解事件必須要先知道一下兩個角色 事件發行者,也稱為傳送者 sender 說白了就是乙個物件,這個物件會自身維護本身的狀態資訊。當自身狀態資訊發生變動時,就...

委託和事件 11 事件本質論

event會自動生成乙個private delegate變數和兩個函式 add和remove,c 編譯器用這兩個方法支援 和 操作符。c net。public event mydelegate onevent 內部實現是 示例性 private mydelegate onevent public v...

C 事件 探尋事件本質

如何定義乙個事件?語法 訪問修飾符 event關鍵字 委託類名 事件名 比如 public event somedelegatename myeventname 事件到底是什麼型別 引用?值?事件其實就是乙個特殊的委託。msdn中的c 參考裡這樣描述 事件是特殊型別的多路廣播委託,僅可從宣告它們的類...