C 中的委託和事件(三)

2021-06-18 03:43:03 字數 4303 閱讀 3116

事件的由來

我們繼續思考上面的程式:上面的三個方法都定義在programe類中,這樣做是為了理解的方便,實際應用中,通常都是 greetpeople 在乙個類中,chinesegreeting和 englishgreeting 在另外的類中。現在你已經對委託有了初步了解,是時候對上面的例子做個改進了。假設我們將greetingpeople()放在乙個叫 greetingmanager的類中,那麼新程式應該是這個樣子的:

以下為引用的內容:

view plain

copy to clipboard

print?

namespace delegate   

}   

class program   

private static void chinesegreeting(string name)   

static void main(string args)   

}   

}  

namespace delegate } class program private static void chinesegreeting(string name) static void main(string args) } }

這個時候,如果要實現前面演示的輸出效果,main方法我想應該是這樣的:

以下為引用的內容:

view plain

copy to clipboard

print?

static void main(string args)   

static void main(string args)

我們執行這段**,嗯,沒有任何問題。程式一如預料地那樣輸出了:

morning, jimmy zhang

早上好, 張子陽

以下為引用的內容:

view plain

copy to clipboard

print?

static void main(string args)   

輸出:morning, jimmy zhang

早上好, jimmy zhang

到了這裡,我們不禁想到:物件導向設計,講究的是物件的封裝,既然可以宣告委託型別的變數(在上例中是delegate1),我們何不將這個變 量封裝到 greetmanager類中?在這個類的客戶端中使用不是更方便麼?於是,我們改寫greetmanager類,像這樣:

以下為引用的內容:

view plain

copy to clipboard

print?

public class greetingmanager   

//在greetingmanager類的內部宣告delegate1變數   

public greetingdelegate delegate1;         

public void greetpeople(string name, greetingdelegate makegreeting)   

}  

public class greetingmanager }

現在,我們可以這樣使用這個委託變數:

以下為引用的內容:

view plain

copy to clipboard

print?

static void main(string args)   

static void main(string args)

儘管這樣達到了我們要的效果,但是似乎並不美氣,光是第乙個方法註冊用「=」,第二個用「+=」就讓人覺得彆扭。此時,輪到event出場了,c# 中可以使用事件來專門完成這項工作,我們改寫greetingmanager類,它變成了這個樣子:

以下為引用的內容:

view plain

copy to clipboard

print?

public class greetingmanager   

}  

public class greetingmanager}

很容易注意到:makegreet 事件的宣告與之前委託變數delegate1的宣告唯一的區別是多了乙個event關鍵字。看到這裡,你差不多明白到:事件其實沒什麼不好理解的,宣告乙個事件不過類似於宣告乙個委託型別的變數而已。

我們想當然地改寫main方法:

以下為引用的內容:

view plain

copy to clipboard

print?

static void main(string args)   

greetingmanager gm = new   greetingmanager();   

gm.makegreet = englishgreeting;   

// 編譯錯誤1   

gm.makegreet += chinesegreeting;   

gm.greetpeople("jimmy zhang", gm.makegreet);   

//編譯錯誤2   

}  

static void main(string args)

這次,你會得到編譯錯誤:事件「delegate.greetingmanager.makegreet」只能出現在 += 或 -= 的左邊(從型別「delegate.greetingmanager」中使用時除外)。

事件和委託的編譯**

這時候,我們不得不注釋掉編譯錯誤的行,然後重新進行編譯,再借助reflactor來對 event的宣告語句做一**,看看為什麼會發生這樣的錯誤:

public event greetingdelegate makegreet;

可以看到,實際上儘管我們在greetingmanager裡將 makegreet 宣告為public,但是,實際上makegreet會被編譯成 私有字段,難怪會發生上面的編譯錯誤了,因為它根本就不允許在greetingmanager類的外面以賦值的方式訪問。

我們進一步看下makegreet所產生的**:

以下為引用的內容:

view plain

copy to clipboard

print?

private greetingdelegate makegreet;   

//對事件的宣告 實際是 宣告乙個私有的委託變數   

[methodimpl(methodimploptions.synchronized)]   

public void add_makegreet(greetingdelegate value)   

[methodimpl(methodimploptions.synchronized)]   

public void remove_makegreet(greetingdelegate value)   

private greetingdelegate makegreet; //對事件的宣告 實際是 宣告乙個私有的委託變數[methodimpl(methodimploptions.synchronized)] public void add_makegreet(greetingdelegate value)[methodimpl(methodimploptions.synchronized)]public void remove_makegreet(greetingdelegate value)

現在已經很明確了:makegreet 事件確實是乙個greetingdelegate型別的委託,只不過不管是不是宣告為public,它總是被宣告為private。另外,它還有兩個方 法,分別是add_makegreet和remove_makegreet,這兩個方法分別用於註冊委託型別的方法和取消註冊,實際上也就是: 「+= 」對應 add_makegreet,「-=」對應remove_makegreet。而這兩個方法的訪問限制取決於宣告事件時的訪問限制符。

在add_makegreet()方法內部,實際上呼叫了system.delegate的combine()靜態方法,這個方法用於將當前的變數新增到委託鍊錶中。我們前面提到過兩次,說委託實際上是乙個類,在我們定義委託的時候:

public delegate void greetingdelegate(string name);

當編譯器遇到這段**的時候,會生成下面這樣乙個完整的類:

以下為引用的內容:

view plain

copy to clipboard

print?

public class greetingdelegate:system.multicastdelegate   

關於這個類的更深入內容,可以參閱《clr via c#》等相關書籍,這裡就不再討論了。

C 中的委託和事件 三

1 匿名方法 到目前為止,要想使委託工作,方法必須已經存在 即委託是用方法的簽名定義的 但使用委託還有另外一種方式 即通過匿名方法。匿名方法是用作委託引數的乙個 塊。用匿名方法定義委託的語法與前面的定義並沒有什麼區別。但在例項化委託時,就有區別了。下面是乙個非常簡單的控制台應用程式,說明了如何使用匿...

C 中的委託和事件

委託類似於c 中的函式指標,c 中的委託申明如下 delegate void mydelegate 只要該委託執行的方法與委託申明的簽名一致,就能呼叫委託來執行該方法,例如在本例中,有個方法為 void method 那麼就可以如下呼叫 mydelegate delegate new mydeleg...

C 中的委託和事件

委託 和 事件在 net framework中的應用非常廣泛,然而,較好地理解委託和事件對很多接觸c 時間不長的人來說並不容易。它們就像是一道檻兒,過了這個檻的人,覺得真是太容易了,而沒有過去的人每次見到委託和事件就覺得心裡憋得慌,渾身不自在。本文中,我將通過兩個範例由淺入深地講述什麼是委託 為什麼...