在C#中我們經常會碰到事件,尤其是在WPF或者WinForm中,窗體加載、或者點擊一個按鈕,都會觸發事件。實際上,事件是對委托的封裝。如果不進行封裝,讓委托暴露給調用者,調用者就可以把委托變量重新引用到新的委托對象,也就刪除了當前要調用的方法列表;更糟糕的是,公共的委托成員打破了封裝不僅導致代碼難以維護和調試,而且會導致應用程序有安全風險。下面分別說明。
1、委托
委托可以理解為一種協議。委托,是什么意思呢?舉個例子,你碰到一件事,你需要讓別人來幫你做(可能你還有別的事情要做),這就是委托,把你現在不能做的事讓別人去做。為什么說委托就像一個協議呢,因為你不想把事情搞砸了,所以你“委托”的這個人做的這件事,你需要給他定一個標准。在C#中就是給所委托的對象定義好簽名,參數有幾個,分別是什么類型,委托方法需要反饋給你什么東西(或者不反饋)。從這種意義上理解,委托就像是一種協議。下面是例子。
上述例子中public delegate int MyDelegate(int x, int y);聲明了一個委托,告訴被委托者這件事你要這么干,我給你兩個整數,你計算他們的和,怎么計算我不管,計算完之后你把和給我。
2、事件
在某件事情發生時,一個對象可以通過事件通知另一個對象。比如,前台界面一個求和按鈕被點擊了,他通知你,可以把a和b這兩個數相加了。這就是一個事件。可以看出事件是在一個時間節點去觸發另外一件事情,而另外一件事情怎么去做,他不會關心。就事件來說,關鍵點就是什么時候,讓誰去做。
在編譯器處理event關鍵字時,會自動提供注冊和注銷方法以及任何必要的委托類型成員變量(私有的),因此不能從觸發事件的對象去調用它們,event關鍵字就像一個語法糖,節省了我們打字的時間。
定義一個事件有兩步,首先定義一個委托,它包括了這件事的“協議”和委托方法(由誰去做);其次,用event關鍵字和相關委托聲明這個事件。事件像是一個接口,封裝了委托所定的“協議”。由於委托已經定義了協議,剩下的就是按這個協議去辦事,至於怎么做它並不關心。下面是一個例子。
從上面可以看出,調用者無法訪問委托對象。
3、回調函數
回調函數就是把一個方法的傳給另外一個方法去執行。回調函數只是一個功能片段,由用戶按照回調函數的調用約定來實現的一個函數。先看一個例子。
可以看出,可以把任意一個符合這個委托的方法傳遞進去,意思就是說這部分代碼是可變的。而設計上有一個抽離出可變部分代碼的原則,這種用法無疑可以用到那種場合了。
以上是個人理解,如果有不合理的地方歡迎交流。