看看這個常常被初級程式設計師弄不懂的 「事件」

2021-06-25 22:42:05 字數 2846 閱讀 4247

眾所周知在面試中,經常有些崽子面試官會問些「事件和委託」的關係,也許一路走來的程式設計師大多都會被問到這個,那麼對於這個

高頻的」事件和委託「問題,如何回擊呢?首先我從最經典的一套面試題說起,用事件來實現 「貓爪老鼠「,這是乙個從網上copy過來的一

個例子。

static

void main(string

args)

}public

delegate

void

cryeventhandler();

public

class

cat

public

virtual

void

oncry()}}

public

class

mouse

public

void

run()

}

事件定義啥的什麼玩意這個我就不說了,沒什麼意思,為了了解這個跟委託有什麼關係,下面我們來看看這段**最後生成的il是什麼樣的。

1:cryeventhandler委託

1

public

delegate

void cryeventhandler();

這個我想大家都清楚,委託本質上是乙個繼承於multicastdelegate的類,同時會生成僅有的4個方法,看下il即知。

2:cat類

1

public

class

cat2910

public

virtual

void

oncry()

1117

}18 }

從這個類中,我們看到了乙個cry事件,然後就是乙個cry.invoke(),不過當你看到invoke的時候,你是不是很懷疑cry是不是乙個委託欄位呢?

其實你懷疑的是一點問題都沒有,32個讚,看下il。

從上圖中我們看到了兩個好玩的東西:

① field cry 字段,完整定義如下,然來所謂的「事件字段」 其實在il下面蛻變成了委託字段,如果你覺得很奇怪,請看第二點。

.field private

static

class sample.cryeventhandler cry

② add_cry,remove_cry,如果僅僅將事件字段變成委託字段,那確實是編譯器在發什麼神經,然來編譯器還給事件配備了兩個方法,這個

其實也就是事件裡面+=,-=的奧秘所在,下面我們挑add_cry方法說下,看看方法定義的il**是怎麼樣的。

很新奇,我們找到了combine方法,這個我們都知道,原來事件中的+=,其實就是利用combine來將當前的委託例項放到delegate的

委託鍊錶中(其實裡面是array實現的),為了方便理解,我把上面的il**翻譯成c#**。

1

public

class

cat2

1819

public

void

remove_cry(cryeventhandler cryeventhandler)

2025

26public

cat()

2730

31public

virtual

void

oncry()

3240

}41 }

可能有些同學對il指令不是很熟悉,沒關係,我也一樣,咱上面有位大神飛鳥的一篇il指令集的博文或許能幫得到你。

3:mouse類

如果你對cat類的il**琢磨的差不多的話,下面這個mouse類就非常簡單了,僅僅呼叫而已嘛。

1

public

class

mouse28

9public

void

run()

1013 }

這個地方最讓人關心的就是:cat.cry += new cryeventhandler(run) 這個語句,從它的il中可以看到其實做了三件事。

① ldftn:       將run方法的非託管指標推送到計算堆疊上。

② newobj:   將cryeventhandler委託new一下,同時將計算堆疊上的run方法的非託管指標作為建構函式的引數。

③ call:         呼叫cat類的add_cry方法,將cryeventhandler的例項作為引數傳遞下去。

下面繼續將該il**反編譯回來,不過針對il指令:call       void sample.cat::add_cry(class sample.cryeventhandler)

並沒有很好的翻譯過來,只能new cat()了一下才能呼叫add_cry,從而觸發了cat的建構函式。

1

public

class

mouse215

16public

void

run()

1720 }

好了,說了這麼多,應該也有總結性的東西出來了,原來事件是完完全全的建立在委託的基礎上,你可以認為事件就是用委託來玩乙個

觀察者模式的,你甚至可以認為事件就是委託。沒有本質區別。

幫忙看看 這個錯誤

include include class teacher char name 5 int age char char address 20 int number char title 10 public void set char int,char,char int,char virtual vo...

看看這個StringBuffer的問題

提供乙個方法 public static void getbuffer stringbuffer x,stringbuffer y public static void main string args stringbuffer x new stringbuffer x stringbuffer y...

請教高手看看這個問起!

我想判斷表單獲取的procompare為空時返回上乙個頁面,不為空時之行下一句compare trim subid trim request.form procompare 或者把procompare引數用alert彈出來!if request.form procompare value then ...