一、委託的簡介
二、事件的簡介
三、委託和事件的使用
四、總結
一、委託的簡介
1、委託的宣告:
delegate handlername ([parameters])
例如:public delegate void printhandler(string str);
委託宣告定義了一種型別,它用一組特定的引數以及返回型別來封裝方法。對於靜態方法,委託物件封裝要呼叫的方法。對於例項方法,委託物件同時封裝乙個例項和該例項上的乙個方法。如果您有乙個委託物件和一組適當的引數,則可以用這些引數呼叫該委託。
2、委託的使用:
using system;
public class myclass
}public delegate void printhandler(string str); // 宣告委託型別
public class printstr
}在c#中使用委託方法:
· 建立委託所使用的方法必須和委託宣告相一致(引數列表、返回值都一致)
· 利用 +=、-=來進行委託的鏈結、取消鏈結或直接使用delegate.combine和delegate.remove方法來實現
· 可以使用multicastdelegate的例項方法getinvocationlist()來獲取委託鏈中所有的委託
· 不能撰寫包含 out 引數的委託
二、事件的簡介
c# 中的"事件"是當物件發生某些事情時,類向該類的客戶提供通知的一種方法。
1、事件的宣告:
宣告的格式為: event eventname
因為使用委託來宣告事件,所以在類裡宣告事件時,首先必須先宣告該事件的委託型別(如果尚未宣告的話)。在上面我們已經提到過了委託型別的宣告,但是在.net framework下為事件使用的委託型別進行宣告時有更嚴格的規定:
(1)、 事件的委託型別應採用兩個引數;
(2)、兩個引數分別是:指示事件源的"物件源"引數和封裝事件的其他任何相關資訊的"e"引數;
(3)、"e"引數的型別應為eventargs 類或派生自 eventargs 類。
如下的定義:
public delegate void printhandler(object sender,system.eventargs e);
然後我們才能宣告該委託型別的事件
例如:public event printhandler print;
當事件發生時,將呼叫其客戶提供給它的委託。
2、呼叫事件:
類宣告了事件以後,可以就像處理所指示的委託型別的字段那樣處理該事件。如果沒有任何客戶將委託與該事件繫結,則該字段將為空;否則該欄位引用應在呼叫該事件時呼叫的委託。因此,呼叫事件時通常先檢查是否為空,然後再呼叫事件。(呼叫事件,即觸發事件,只能從宣告該事件的類內進行)
if(print != null)
3、事件繫結:
從類的外面來看,事件就象類的乙個公共成員,通過 類名.事件名 的形式來訪問,但是只能對它做繫結和解除繫結的操作,而不能有其他操作。
類名. print += new printhandler(繫結的方法名) // 將某個方法繫結到print事件上
類名. print -= new printhandler(繫結的方法名) // 將某個已繫結到print事件上的方法從print事件上解除
三、委託和事件的使用
委託和事件在使用者介面程式裡用的比較的多,比如象在winform或webform的使用者ui上的button和它的click事件:
// 將button1_click()方法繫結到按鈕控制項button1的click事件上
this.button1.click += new system.eventhandler(this. button1_click);
private void button1_click(object sender, system.eventargs e) // button1_click()方法
然而除了使用者介面程式外,在很多其他地方也用到了事件驅動模式,比如觀察者模式(observer)或發布/訂閱(publish/subscribe)裡:在乙個類裡發布(publish)某個可以被觸發的事件,而其他的類就可以來訂閱(subscribe)該事件。一旦這個發布者類觸發了該事件,那麼執行時環境會立刻告知所有訂閱了該事件的訂閱者類:這個事件發生了!從而各個訂閱者類可以作出它們自己的反應(呼叫相應方法)。
我們來舉乙個生活中的實際例子來說明如何使用委託和事件,以及使用委託和事件所帶來的好處:
比如說有乙個公司(場景),你是老闆,手下有主管和員工,作為老闆你會指派(委託)主管管理員工的工作,如果某個員工玩遊戲,則讓某個主管從該員工的薪水裡扣去500元錢。
這就是現實中的委託。
而在寫程式中,假設程式設計師就是老闆,有兩個類分別為主管和員工,而主管小王和員工小張就是兩個類的物件例項。員工類有乙個方法:玩遊戲,同時就有乙個玩遊戲的事件,他一玩遊戲就會激發這個事件。而主管類就是負責處理該事件的,他負責把玩遊戲的員工的薪水扣除500。
(一)、首先,我們來看看在非委託的情況下比較常見的一種設計方式(當然這不是唯一的方式,也不是最好的方式,但是很常見):
這種方法所帶來的問題: 員工類和主管類的耦合性太高
1、 在客戶程式裡必須先建立了主管類之後才能生成員工類,如果在不需要主管類物件而只需員工類物件的地方,為了建立所需的員工類物件例項,你也不得不去先建立乙個主管類的物件例項;
2、 如果場景劇本(即客戶程式需求)發生了變化
(1)、現在要讓乙個新的角色(乙個新的類),如保安,來代替主管,負責在員工玩遊戲時扣員工薪水,那麼我們不得不去修改員工類,或許還需要修改主管類;
(2)、如果場景劇本增加新的需求,要求員工在玩遊戲後,不但要扣薪水,還要在績效上扣分,那麼我們也不得不修改員工類。
(二)、利用委託的實現:
下面有個例子:在c# 控制台應用程式編輯執行成功:
using system;
namespace csharpconsole
public void 扣薪水(object sender,eventargs e)
}// 如果玩遊戲,則會引發事件
public class 員工
public int 薪水 // 此屬性可以操作員工的薪水 。
set}
public void 玩遊戲()
protected virtual void onplaygame(eventargs e)}}
public class 場景}}
對於前面提出的問題:
1、 解耦了主管類和員工類之間的必然聯絡,可以單獨建立員工類物件例項,而不用管是否有主管類物件例項的存在;
2、 在客戶程式需求變化時:
(1)、我們只需修改客戶程式,即上面例子裡的class 場景,將委託改為如下:
保安 小李 = new 保安();
小張.playgame += new playgamehandler(小李. 扣薪水);
即可實現由保安來負責扣薪水的需求變化,而不用動員工類。
(2)、我們只需修改客戶程式,即上面例子裡的class 場景,新增乙個如下的委託:
小張.playgame += new playgamehandler(某某. 扣績效分);
這個"某某"可以是主管,也可以是其他新的角色(新的類),只需要在"某某"對應的類裡定義扣績效分的動作即可,而不用動員工類。
四、總結:
當然,不使用委託和事件我們仍然可以設計出解耦的類,然而卻會增加很多的類、介面以及關聯等等,增加了**量和程式的邏輯複雜性,而在.net裡利用委託和事件我們只需少的多的**來實現。
委託和事件的使用有如下幾個要素:
1、激發事件的物件-----就是員工小張
2、處理物件事件的物件-----就是主管小王
3、定義委託,就是你讓主管小王監視員工小張。
如果這三個要素都滿足的話,則你就寫出了乙個完整事件的處理。
我們把上面的例項寫成完整的原始碼:
using system;
public delegate void playgamehandler(object sender, eventargs
e);public class manager
public void submoney(object sender, eventargs e)
}public class employee
public int money
set}
public void playinggame()
protected virtual void onplaygame(eventargs e)}}
public class exwebdelegate2}
C 事件 事件解析
事件 event 這個詞兒對於初學者來說,往往總是顯得有些神秘,不易弄懂。而這些東西卻往往又是程式設計中常用且非常重要的東西。大家都知道windows訊息處理機制的重要,其實c 事件就是基於windows訊息處理機制的,只是封裝的更好,讓開發者無須知道底層的訊息處理機制,就可以開發出強大的基於事件的...
C 事件例子
這是乙個簡單的c 事件例子,是在別人的基礎上的總結 事件發生等於呼叫這個事件,事件當做函式來呼叫,為什麼能當做函式來呼叫呢,因為事件 它是委託的例項,委託是一種資料型別,是給方法定義型別的,它定義了函式的簽名,更深層次的說,事件它是委託鏈,那麼就需要呼叫委託鏈中的所有方法.事件用的時候相當於乙個函式...
js 事件 事件物件
關於事件寫了一系列文章 1.事件流 事件捕獲和事件冒泡 2.事件處理程式 3.事件物件 本文介紹事件物件 4.通用的事件偵聽器函式 5.事件迴圈 event loop 6.事件 event delegation 1.事件物件 觸發dom上的某個物件時,會產生乙個事件物件event dom0級事件物件...