關於委託和事件

2021-06-15 21:03:18 字數 3249 閱讀 1384

委託(delegate) 是一種資料結構,它引用靜態方法或引用類例項及該類的例項方法。它宣告定義一種引用型別,該型別可用於將方法用特定的簽名封裝。委託例項封裝靜態方法或例項方法。委託大致類似於 c++ 中的函式指標;但是,委託是型別安全和可靠的。

宣告採用下列形式:

[attributes] [modifiers] delegate result-type identifier ([formal-parameters]);

其中:

attributes(可選)

附加的宣告性資訊。有關屬性和屬性類的更多資訊,請參見 17. 屬性。

modifiers(可選)

允許使用的修飾符有 new 和四個訪問修飾符。

result-type

同方法的返回型別匹配的結果型別。

identifier

委託名稱。

formal-parameters(可選)

引數列表。如果引數是乙個指標,則必須用 unsafe 修飾符宣告委託。

注意:委託使您得以將函式作為引數傳遞。委託的型別安全要求作為委託傳遞的函式擁有同委託宣告相同的簽名。

一、介面

如果你定義了類a,但是你希望它的方法能和其他類共享——但很多情況下,共享是必要的,例如有10個不同的類都要實現該方法,重複地將這個方法宣告10遍是無法令人接受的。

於是你將許多人的相同的願望抽象為inte***ce(介面),如:

inte***ce iobjectmove

這樣,同樣的方法可以被應用於多個地方,就像模板一般:

class a : iobjectmove

public void moveprocessing()

public int movecompleted()

}class b : iobjectmove

public void moveprocessing()

public int movecompleted()

}二、委託

a和b所實現的方法本身可能完全一樣,但是a或許方法moveprocessing()並不感興趣。在這種情況下,介面的粒度不夠小(建立過小的介面會造成資源浪費)。於是希望能夠為每個方法建立乙個小型介面,稱之為委託(delegate):

delegate void movestarted();

delegate void moveprocessing();

delegate int movecompleted();

在class c中有如下宣告:

class c

如此一來,class a和class b的**可能變成了這樣:

class a

public int movecompleted()

}class b

}在執行**裡需要實現委託,假設class a的乙個例項(ample)需要實現乙個委託movestarted,這個委託是class c的例項(notry)的一成員cmovestarted。則可能需要通過賦值運算子來進行:

notry.cmovestarted=new movestarted(ample.movestarted);

這很容易理解,但是這樣做存在兩個嚴重的隱患:

第一、作為class c的公共成員,cmovestarted允許外來呼叫,安全性勢必沒有保障,class a和class b都有可能出現越界的行為,這是我們不願意看到的。

第二、如果class b的例項eboy也需要實現同樣的委託,則:

notry.bmovestarted=new movestarted(eboy.bknowmovestarted);

很遺憾,這樣產生的後果是class b的委託取代了class a的委託。

三、事件

理想的解決辦法是通過註冊和反註冊函式來新增或移除自己的委託,而不允許直接對別人的委託進行操作。可以通過在class c宣告成員時使用event關鍵字來實現:

//之前的宣告是:public void movestarted cmovestarted;

public event movestarted cmovestarted;

public event moveprocessing cmoveprocessing;

public event movecompleted cmovecompleted;

有了event的約束,使用者便只能通過+=和-=來新增和移除委託:

notry.cmovestarted += new movestarted(ample.aknowmovestarted);

notry.cmovestarted += new movestarted(eboy.bknowmovestarted); //最終是新增的效果而非取代

//移除

notry.cmovestarted -= new movestarted(ample.aknowmovestarted);

notry.cmovestarted -= new movestarted(eboy.bknowmovestarted);

四、總結

1、介面固然好,但始終關注它的粒度是否合適,應為一旦工程發布,修改或刪除介面將是很危險的事情。

2、要使用事件(event)來約束委託行為。

委託是一種安全地封裝方法的型別,它與 c 和 c++ 中的函式指標類似。與 c 中的函式指標不同,委託是物件導向的、型別安全的和保險的。委託的型別由委託的名稱定義。下面的示例宣告了乙個名為del的委託,該委託可以封裝乙個採用字串作為引數並返回 void 的方法。

c#

public delegate void del(string message);

構造委託物件時,通常提供委託將包裝的方法的名稱或使用匿名方法。例項化委託後,委託將把對它進行的方法呼叫傳遞給方法。呼叫方傳遞給委託的引數被傳遞給方法,來自方法的返回值(如果有)由委託返回給呼叫方。這被稱為呼叫委託。可以將乙個例項化的委託視為被包裝的方法本身來呼叫該委託。例如:

c#

// create a method for a delegate.

public static void delegatemethod(string message)

// instantiate the delegate.

del handler = delegatemethod;

// call the delegate.

handler("hello world");

關於事件委託

首先,先來看乙個例子 如微博,每一條博文都有事件,如增加 刪除等!這樣子的話我們每次發微博的時候就得在建立的時候把該有的事件給加上。html js var otext document.getelementbyid txt1 var obtn document.getelementbyid btn1...

委託和事件

主要過程如下 1.在後台 中,我們可以定義處理程式方法alartrang 2.然後定義委託,引用到處理程式方法的例項。3.最後將委託新增到事件中。從而,引發事件時就會呼叫相關的事件處理方法。若要使用在另乙個類中定義的事件,必須定義和註冊乙個事件處理程式。事件 處理程式必須具有與為事件宣告的委託相同的...

委託和事件

委託的宣告 public delegate void mydelegate string str 注1.委託的定義和方法的定義類似,只是在前面加了乙個delegate,但委託不是方法,它是一種型別。是一種特殊的型別,看成是一種新的物件型別比較好理解。用於對與該委託有相 同簽名的方法呼叫。2.委託相當...