眾所周知在面試中,經常有些崽子面試官會問些「事件和委託」的關係,也許一路走來的程式設計師大多都會被問到這個,那麼對於這個
高頻的」事件和委託「問題,如何回擊呢?首先我從最經典的一套面試題說起,用事件來實現 「貓爪老鼠「,這是乙個從網上copy過來的一
個例子。
static事件定義啥的什麼玩意這個我就不說了,沒什麼意思,為了了解這個跟委託有什麼關係,下面我們來看看這段**最後生成的il是什麼樣的。void main(string
args)
}public
delegate
void
cryeventhandler();
public
class
cat
public
virtual
void
oncry()}}
public
class
mouse
public
void
run()
}
1:cryeventhandler委託
1這個我想大家都清楚,委託本質上是乙個繼承於multicastdelegate的類,同時會生成僅有的4個方法,看下il即知。public
delegate
void cryeventhandler();
2:cat類
1從這個類中,我們看到了乙個cry事件,然後就是乙個cry.invoke(),不過當你看到invoke的時候,你是不是很懷疑cry是不是乙個委託欄位呢?public
class
cat2910
public
virtual
void
oncry()
1117
}18 }
其實你懷疑的是一點問題都沒有,32個讚,看下il。
從上圖中我們看到了兩個好玩的東西:
① field cry 字段,完整定義如下,然來所謂的「事件字段」 其實在il下面蛻變成了委託字段,如果你覺得很奇怪,請看第二點。
.field private② add_cry,remove_cry,如果僅僅將事件字段變成委託字段,那確實是編譯器在發什麼神經,然來編譯器還給事件配備了兩個方法,這個static
class sample.cryeventhandler cry
其實也就是事件裡面+=,-=的奧秘所在,下面我們挑add_cry方法說下,看看方法定義的il**是怎麼樣的。
很新奇,我們找到了combine方法,這個我們都知道,原來事件中的+=,其實就是利用combine來將當前的委託例項放到delegate的
委託鍊錶中(其實裡面是array實現的),為了方便理解,我把上面的il**翻譯成c#**。
1可能有些同學對il指令不是很熟悉,沒關係,我也一樣,咱上面有位大神飛鳥的一篇il指令集的博文或許能幫得到你。public
class
cat2
1819
public
void
remove_cry(cryeventhandler cryeventhandler)
2025
26public
cat()
2730
31public
virtual
void
oncry()
3240
}41 }
3:mouse類
如果你對cat類的il**琢磨的差不多的話,下面這個mouse類就非常簡單了,僅僅呼叫而已嘛。
1這個地方最讓人關心的就是:cat.cry += new cryeventhandler(run) 這個語句,從它的il中可以看到其實做了三件事。public
class
mouse28
9public
void
run()
1013 }
① 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 ...