C#基礎系列:再也不用擔心面試官問我“事件”了

發表於2016-02-26

前言:作為.Net攻城獅,你面試過程中是否遇到過這樣的問題呢:什麼是事件?事件和委託的區別?既然事件作為一種特殊的委託,那麼它的優勢如何體現?諸如此類…你是否也曾經被問到過?你又是否都答出來了呢?

關於面試中涉及到的事件的問題,我們只需要抓住幾個關鍵點就好了:

(1)事件是委託的封裝,可以理解為一種特殊的委託。

(2)事件裡面其實就兩個方法(即add_event()和remove_event())和一個私有的委託變數,這兩個方法裡面分別是對這個私有的委託變數進行的合併和移除,當呼叫事件的+=時其實是呼叫的事件裡面的add_event()方法,同樣-=呼叫的是remove_event()方法。

(3)事件只能夠從物件外部增加新的響應方法和刪除已知的響應方法,而不能主動去觸發事件和獲取其他註冊的響應方法等資訊。如果使用公有的delegate則不能做這些限制,也就是說事件對委託做了限制,使委託使用起來更加方便。也有人說事件是對委託的閹割,大概也是這個意思。

如果回答的時候抓住了以上的3點,那麼我想你的面試應該不會太差。畢竟面試那麼短的時間,有一兩個亮點就很不錯了,你說呢。哪怕你對事件機制完全不懂,為了面試記住其中兩點也是很好的,工作經驗我們們沒有,換工作的經驗可不能沒有哦~~扯遠了,關於面試就到此為止。如果你還想繼續將事件瞭解透徹,彆著急,慢慢往下看。

1、事件的定義及由來:

定義事件:

將這段程式碼生成dll後,通過反編譯工具reflector我們可以看到:

c# 基礎事件

正如上文所說,可以看到當定義一個事件public event MyStudyEvent eMyStudyEvent的時候,編譯器會自動給他生成兩個方法add和remove,以及一個private的委託變數eMyStudyEvent。我們將反編譯程式碼copy出來看看。

可以看到這兩個方法的主要作用就是在向private變數eMyStudyEvent裡面新增委託和移除委託。當呼叫事件的+=和-=時,eMyStudyEvent裡面就合併和移除傳過來的委託,當事件觸發的時候,eMyStudyEvent變數就執行。這樣設計也正好符合封裝的原則,保證了內部變數的安全性。

2、Framework裡面的事件:既然自定義的事件是這樣的,那麼有人就要問了,.Net裡面的事件是否也是如此。我們直接通過反編譯工具來看。我們找到System.Windows.Forms下面的Button類,這個也是我們Winform裡面使用最多的按鈕,我們來看看我們經常使用的事件。

c# 基礎系列

base.DoubleClick轉到定義:

c#基礎系列

Events.AddHandler()轉到定義:

c#基礎系列

是不是很眼熟,也是通過Delegate.Combine()來合併委託。

3、自定義事件的使用。事件使用的例子園子裡面文章也很多,此片博主就以監聽資料夾裡面的1.txt檔案是否存在為例說明事件的使用以及使用事件和委託的區別。

首先定義事件以及觸發事件的方法:

然後在Main函式裡面啟動監聽以及定義事件處理方法:

啟動程式後,每當在資料夾裡面刪除和建立1.txt的時候就會列印提示檔案改變。

c#基礎系列

博主好奇心重,貌似這種監聽直接用委託也可以實現了。於是乎將event事件變數直接改成委託變數。

然後執行。發現可以得到一樣的結果。

只是在反編譯的時候沒有add和remove方法而已:

c#基礎系列

這裡正是需要說明的上面的面試回答第三條:事件只能通過+=和-+去閹割委託,而不能主動觸發事件。如當使用事件的機制public event FileWatchEventHandler FileWatchEvent時。在Main函式裡面

這樣寫是會報錯的FileWatchEventSource.FileWatchEvent(null, null);因為事件不能主動觸發,而改成委託後這樣寫就是正確的。並且如果是event變數,除了+=和-=操作,其他所有操作都會報錯:

c#基礎系列

從這裡可以看出,事件對委託進行了封裝和約束。

總而言之,言而總之,事件和委託,打一個不太恰當的比喻,就類似麵包和麵粉,麵包是由麵粉加工而來的,當我們肚子餓了的時候,麵包直接就能吃,麵粉還需要加工。而當我們需要麵條的時候,麵粉就派上用場了,麵包對於我們來說是用不了的。不知道這樣解釋好理解否。說了這麼多,確實有點繞,需要好好體會下。

本系列:

相關文章