這時候,我們注釋掉編譯錯誤的行,然後重新進行編譯,再借助reflactor來對 event的宣告語句做一**,看看為什麼會發生這樣的錯誤:
可以看到,實際上儘管我們在greetingmanager裡將 makegreet 宣告為public,但是,實際上makegreet會被編譯成 私有字段,難怪會發生上面的編譯錯誤了,因為它根本就不允許在greetingmanager類的外面以賦值的方式訪問,從而驗證了我們上面所做的推論。
我們再進一步看下makegreet所產生的**:
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);
當編譯器遇到這段**的時候,會生成下面這樣乙個完整的類:
關於這個類的更深入內容,可以參閱《clr via c#》等相關書籍,這裡就不再討論了。
上面的例子已不足以再進行下面的講解了,我們來看乙個新的範例,因為之前已經介紹了很多的內容,所以本節的進度會稍微快一些:
假設我們有個高檔的熱水器,我們給它通上電,當水溫超過95度的時候:1、揚聲器會開始發出語音,告訴你水的溫度;2、液晶屏也會改變水溫的顯示,來提示水已經快燒開了。
現在我們需要寫個程式來模擬這個燒水的過程,我們將定義乙個類來代表熱水器,我們管它叫:heater,它有代表水溫的字段,叫做temperature;當然,還有必不可少的給水加熱方法boilwater(),乙個發出語音警報的方法makealert(),乙個顯示水溫的方法,showmsg()。
namespace delegate }}
// 發出語音警報
private
void makealert(int param) 度了:" , param);
}// 顯示水溫
private
void showmsg(int param) 度。" , param);}}
class
program }}
上面的例子顯然能完成我們之前描述的工作,但是卻並不夠好。現在假設熱水器由三部分組成:熱水器、警報器、顯示器,它們來自於不同廠商並進行了組裝。那麼,應該是熱水器僅僅負責燒水,它不能發出警報也不能顯示水溫;在水燒開時由警報器發出警報、顯示器顯示提示和水溫。
這時候,上面的例子就應該變成這個樣子:
// 熱水器
public
class
heater }}
// 警報器
public
class
alarm 度了:" , param);}}
// 顯示器
public
class
display度。" , param);}}
這裡就出現了乙個問題:如何在水燒開的時候通知報警器和顯示器?在繼續進行之前,我們先了解一下observer設計模式,observer設計模式中主要包括如下兩類物件:
subject:監視物件,它往往包含著其他物件所感興趣的內容。在本範例中,熱水器就是乙個監視物件,它包含的其他物件所感興趣的內容,就是temprature欄位,當這個欄位的值快到100時,會不斷把資料發給監視它的物件。
observer:監視者,它監視subject,當subject中的某件事發生的時候,會告知observer,而observer則會採取相應的行動。在本範例中,observer有警報器和顯示器,它們採取的行動分別是發出警報和顯示水溫。
在本例中,事情發生的順序應該是這樣的:
警報器和顯示器告訴熱水器,它對它的溫度比較感興趣(註冊)。
熱水器知道後保留對警報器和顯示器的引用。
熱水器進行燒水這一動作,當水溫超過95度時,通過對警報器和顯示器的引用,自動呼叫警報器的makealert()方法、顯示器的showmsg()方法。
類似這樣的例子是很多的,gof對它進行了抽象,稱為observer設計模式:observer設計模式是為了定義物件間的一種一對多的依賴關係,以便於當乙個物件的狀態改變時,其他依賴於它的物件會被自動告知並更新。observer模式是一種松耦合的設計模式。
C 委託和事件(3)
面試例題4 舉例說明匿名方法。考點 匿名方法的作用,匿名方法的使用方法。出現頻率 解答匿名方法用於簡化事件註冊方法的編寫過程,可以直接將方法體的 和委託物件相關聯而不需要單獨定義這個方法。本例程式仍然實現eventdel.cs的相同功能,只是將事件處理方法更改為匿名方法,並且在name類中將觸發事件...
C 中的Func委託和Action委託
委託時物件導向的程式語言中新加入的一種特性,在c 中引入委託使得c 程式的編寫更加靈活。c 中可以自己定義各種各樣的委託,但是c 語言也預先為我們定義了兩個做常用的委託,乙個是func乙個是action.函式最基本的特點就是輸入輸出,即輸入引數 執行運算 輸出引數,action是一類沒有輸出引數的委...
C 中的委託和事件
委託類似於c 中的函式指標,c 中的委託申明如下 delegate void mydelegate 只要該委託執行的方法與委託申明的簽名一致,就能呼叫委託來執行該方法,例如在本例中,有個方法為 void method 那麼就可以如下呼叫 mydelegate delegate new mydeleg...