另類的思維 將事件視為對象
將事件視為對象,有的時候就是把事件的級別進(jìn)行了提升,這樣就能有效地提高語言的抽象能力。有的時候會出現(xiàn)錯誤,但還是值得嘗試的。
如果一個語言(平臺)把事件視為對象,則表明它把“事件”作為了語言的一等公民來對待。這意味著,我們可以把一個單獨的事件作為參數(shù)傳遞給方法,也可以將其作為一個對象的一部分,這有效地提高語言的抽象能力。試想,如果沒有“委托”,在.NET中就無法把“方法”看作是對象,也就很難使用如今各種靈活的抽象方式。同樣,由于.NET本身無法將事件作為單個對象處理,因此在某些時候就會束手束腳,也難以引入一些特別的編程模型。
這就是“把事件作為對象進(jìn)行傳遞”的實際意義。
在上一篇文章里,我們提出了一種“解決方案”,它允許我們編寫這樣的代碼:
- class Program
- {
- public event EventHandler Submit;
- static void Main(string[] args)
- {
- Program p = new Program();
- var ev = EventFactory.Create(() => p.Submit);
- ev += (sender, eventArgs) => Console.WriteLine(sender);
- p.Submit("Hello World", EventArgs.Empty);
- Console.WriteLine("Press any key to exit...");
- Console.ReadLine();
- }
- }
看上去挺那么像回事兒的,使用方式和傳統(tǒng)的事件似乎沒有太大區(qū)別。但是文末我提到這里其實有些“糊弄”的意味,而我們的裝配腦袋同學(xué)、以及“腦袋裝配得不輸給裝配腦袋”的RednaxelaFX,這兩位純爺們也都指出了問題。
信腦袋,得永生。信RednaxelaFX,原地滿狀態(tài)復(fù)活。
以上代碼的“忽悠”,在于操作Program.Submit的代碼處于Program類之內(nèi)。如果我們想要使用相同的做法操作其他類的事件就做不到了,例如:
- public class MyClass
- {
- public event EventHandler MyEvent;
- }
- class Program
- {
- static void Main(string[] args)
- {
- var myClass = new MyClass();
- var ev = EventFactory.Create(() => myClass.MyEvent);
- }
- }
這樣的代碼看似沒有問題,但是編譯器會提示這樣的錯誤:
The event 'SimpleConsole.MyClass.MyEvent' can only appear on the left hand side of += or -= (except when used from within the type 'SimpleConsole.MyClass')
編譯器告訴我們,除了在MyClass類的內(nèi)部,MyEvent事件只能出現(xiàn)在+=或-=操作的左邊。之前提到的兩位純爺們在前文的評論中也有過相關(guān)及衍生的討論。因此,我們目前的做法是失敗的。
前文的評論中還有朋友提到,我們事實上也可以把一個事件作為參數(shù)傳遞給一個方法(然后在方法里添加或刪除處理程序),只要使用ref關(guān)鍵字就可以了,例如:
- static void RegisterHandlers(ref EventHandler e) { ... }
然后:
- static void Main(string[] args)
- {
- var myClass = new MyClass();
- RegisterHandlers(ref myClass.MyEvent);
- }
不過很顯然,這樣的做法也會遇到相同的問題:除非是Program內(nèi)部的事件,我們不能把它像一個委托對象那樣傳遞。而且,即使可以傳遞,我們也只能為它添加或刪除處理函數(shù),而不能把它作為另一個對象的一部分,然后經(jīng)過各種處理之后,還可以對這個事件進(jìn)行操作。
因此,我們要實現(xiàn)的其實是這樣一個類型:
- public class DelegateEvent
- {
- ...
- public DelegateEvent AddHandler(TDelegate handler) { ... }
- public DelegateEvent RemoveHandler(TDelegate handler) { ... }
- }
這就是今天“趣味編程”的題目:將DelegateEvent<>類型實現(xiàn)完整,并盡可能做到嚴(yán)謹(jǐn)和易用(即適用于各種場合,各種方式進(jìn)行“構(gòu)造”)。
所謂“趣味編程”,是指那些我覺得難度適中的小題目,并可以鍛煉“編程能力”或“語言類庫的掌握程度”。一般來說它們都源自實際項目,只不過改造成“題目”時進(jìn)行了“抽象”和“提煉”。個人認(rèn)為它們還是挺適合作為平時的編程練習(xí)來使用的,感興趣的朋友們不妨一試。
至于題目是否真的有“趣味”……這個見仁見智吧。我想,要讓那些對于那些視編程如磨難的朋友們感到有趣,應(yīng)該不比登天要容易一些。
原文標(biāo)題:趣味編程:將事件視為對象
鏈接:http://www.cnblogs.com/JeffreyZhao/archive/2009/09/09/more-on-event-as-object.html
【編輯推薦】