C#事件實(shí)例詳解
C#和JAVA有許多相似的地方,設(shè)計(jì)思想差不多,語(yǔ)法及其相像,均傳承自面向?qū)ο笤O(shè)計(jì)思想,靈感來(lái)自C++并取其精華去其“糟粕(二字持保留意見)”,中間語(yǔ)言、解釋執(zhí)行、一次編譯、到處執(zhí)行,出身豪門算得上是表兄弟關(guān)系,各自擁有龐大的擁躉,兩種語(yǔ)言在發(fā)展的道路上你追我趕相互借鑒相互學(xué)習(xí)相互滲透,至于誰(shuí)的IDE更強(qiáng)大對(duì)于一個(gè)用了二十年vim編輯器的人來(lái)說(shuō)實(shí)在無(wú)從評(píng)判,強(qiáng)大到讓人內(nèi)牛滿面~
C#語(yǔ)言中關(guān)于事件(event)結(jié)合代理(delegate)實(shí)現(xiàn)對(duì)象狀態(tài)變更時(shí)的通知機(jī)制,總感覺這種處理有點(diǎn)過(guò)于復(fù)雜化了,但既然人家這么設(shè)計(jì)必定有人家的道理,相信并向人家學(xué)習(xí)而不急于批判和否定才能讓自己進(jìn)步的更快,個(gè)人覺得這種處理大概是來(lái)自于視窗系統(tǒng)獨(dú)有的對(duì)各個(gè)控件事件集中快速響應(yīng)的機(jī)制吧,這可能也是從事前后端開發(fā)關(guān)注點(diǎn)的差異,前端重人機(jī)交互當(dāng)然交互的核心就是不確定時(shí)間屬性和狀態(tài)的事件,后端重觸發(fā)每個(gè)事件的發(fā)生基本都是預(yù)定義且流程化構(gòu)建好的,所以接下來(lái)嘗試?yán)斫夂徒庾x一下C#的事件。
第一步:聲明一個(gè)代理,這個(gè)代理可以是系統(tǒng)的也可以是自定義的。
public delegate void MyDelegate(); // 聲明無(wú)參無(wú)返回值代理 public delegate bool MyDelegate(int k, int v); // 聲明有參有返回值代理
第二步:創(chuàng)建一個(gè)包含該代理事件的對(duì)象,對(duì)象中調(diào)用代理實(shí)現(xiàn)事件的處理。
public class MyArrayList : ArrayList { public event MyDelegate MyChanged; // 聲明代理事件 public override void Add(object o) // 覆蓋父類方法 { base.Add(o); // 調(diào)用父類方法 OnChanged(); // 調(diào)用事件函數(shù) } protected virtual void OnChanged() { if (null != MyChanged) MyChanged(); // 代理觸發(fā)事件 } }
第三步:創(chuàng)建一個(gè)類,將事件和代理綁定到一起,a、類構(gòu)造時(shí)以包含代理事件對(duì)象作為入?yún)?,b、“+=”運(yùn)算符實(shí)現(xiàn)綁定,c、在代理中傳入類成員函數(shù)。
public class MyEvent { private MyArrayList list; public MyEvent(MyArrayList l) { list = l; list.MyChanged += new MyDelegate(ListChanged); // 綁定事件 } private void ListChanged() // 被綁定事件 { System.Console.WriteLine("ListChanged ..."); } }
第四步:創(chuàng)建含有事件的類的實(shí)例,創(chuàng)建含有方法的類的實(shí)例。
public class MyTest { public static void Main() { MyEvent me = new MyEvent(new MyArrarList()); me.Add("object_1"); } }
仔細(xì)研究發(fā)現(xiàn),代理相當(dāng)于C\C++中的函數(shù)指針,但功能更強(qiáng)大,使用更安全,代理實(shí)例在創(chuàng)建的時(shí)候,代理會(huì)把傳給它的參數(shù)傳給綁定的方法,而且代理可以通過(guò)“+=”運(yùn)算符搭載更多的方法,下面是對(duì)比C\C++函數(shù)指針的用法。
char* (*pFun)(char*) = NULL; pFun = GtCodeUtf8ToGB2312; char* pszData = (*pFun)("計(jì)算機(jī)"); char* GtCodeUtf8ToGB2312(char* pszUtf8) { char* pszGB2312 = NULL; ...... return pszGB2312; }
再舉兩個(gè)C語(yǔ)言中典型的函數(shù)指針的例子:
例一:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);其中第三個(gè)參數(shù)是一個(gè)函數(shù)地址,指向被創(chuàng)建線程的核心處理函數(shù)。
例二:void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));其中最后一個(gè)參數(shù)也是一個(gè)函數(shù)地址,指向兩個(gè)元素對(duì)比計(jì)算函數(shù)。