C#2.0 委托
委托
委托是一個非常不錯的設(shè)計,允許我們把方法做為參數(shù)傳遞,實(shí)現(xiàn)了開放閉放原則。在方法中我們只要有一個委托占位,調(diào)用者就可以傳入符合簽名的方法來做不同的操作,這也面向?qū)ο箝_發(fā)中多態(tài)的魅力。
但是在C#1.0的時候,委托寫起來實(shí)際上是非常復(fù)雜的,首先我們要聲明一個委托,然后再寫一個符合委托簽名的方法。再創(chuàng)建委托實(shí)例。然后才是調(diào)用,比如下面一個簡單的例子,我要在winform程序中用戶按了按鍵后我需要彈出一個消息
因?yàn)槲械穆暶饕呀?jīng)內(nèi)置了,也就是KeyPressEventHandler所以我不用去寫。簡單一看似乎挺簡潔,但是在winForm程序中會有著大量的事件,有些事件可能處理的方式非常簡單,但是我們需要去相應(yīng)的寫一個方法。這也是比較頭疼的問題。下面我們來看如何優(yōu)化這個代碼
? ?
方法組
在這面我們創(chuàng)建了一個委托實(shí)例,在C#1.0中,要同時指定委托類型和方法(操作)也就是如下圖
而在C#2.0中支持從方法組到一個兼容委托的隱式轉(zhuǎn)換,也就是如果方法簽名和委托聲明完全相同,那么就不必再去new一個委托。這時代碼就變成了
? ?
但是有些方法并不是可以進(jìn)行隱式轉(zhuǎn)換的,如果方法需要一個Delegate類型的參數(shù),那么我們的方法就不適用了,比如Invoke方法。這些我們就要顯示轉(zhuǎn)換
? ?
? ?
協(xié)變與逆變
很多人都以為這是在4.0中才支持的,因?yàn)槟菚r有了泛型的可變性。不過這個委托的可變性完全不同。
在winform中給我們內(nèi)置很多的委托類型,比如上面用到的KeyPressEventHandler,還有MouseEventHandler,他們實(shí)際上區(qū)別不大,只是參數(shù)類型不同。第一個參數(shù)類型是KeyPressEventArgs,第二個是MouseEventArgs。
不同的事件對應(yīng)不同的處理,這是沒有問題的。但是我們可能會有不同的事件同樣的處理這種需求。在C#1.0中很遺憾是沒有辦法的。而在C#2.0中我們可以使用逆變來解決這個問題
KeyPressEventArgs與MouseEventArgs都派生與EventArgs類型。實(shí)際上EventArgs的派生類有多達(dá)數(shù)百個。
我們只需要有一個具有EventAgrs類型的方法,就可以這么去做
? ?
一個返回類型為基類的委托,我們想要用子類去實(shí)例化這個委托,這在之前是不可能的。而在C#2.0中,這已經(jīng)沒有任何問題
? ?
? ?
? ?
匿名方法
在C#2.0中設(shè)計者也意識到了創(chuàng)建一個委托的步驟過于繁瑣,我們要有一個完整的方法,然后再創(chuàng)建委托實(shí)例進(jìn)行調(diào)用,在C#2.0中則出現(xiàn)了匿名方法來幫助我們簡化這一流程(3.0中的拉姆達(dá)則更加的方便)
下面就是一個簡單的匿名方法創(chuàng)建委托實(shí)例的例子,拿到一個字符串然后去除兩邊空格打印出來
? ?
雖然我們創(chuàng)建的是一個委托方法,但是編譯成IL后每個匿名方法都會創(chuàng)建一個方法,會在匿名方法所在的類生成一個方法不過方法名則是亂七八糟的,不過也不是給程序員去看的。
? ?
閉包
使用方法就會使用到變量,對于匿名方法來說,分為外部變量與局部變量。很容易理解,外部變量就是匿名方法外聲明的變量,而局部變量就是匿名方法內(nèi)聲明的變量。
如果匿名方法沒有使用任何外部變量,那么則相安無事。如果使用了外部變量,那么它就是被捕獲的外部變量。在匿名方法內(nèi)對該變量的操作是有效的!
為什么要說閉包,是因?yàn)槟涿椒〞谔爻傻那闆r下延長變量的生命周期,為什么這么說呢,大家都知道委托是方法的類型,可以把方法作為委托進(jìn)行返回,如果一個方法里有一個委托實(shí)例,使用的是匿名方法并且捕獲了外部變量,然后把這個委托實(shí)例進(jìn)行返回。這時就形成了一個閉包
? ?
這時如果去看IL會發(fā)現(xiàn)創(chuàng)建了一個新的類去容納i變量,這也是為什么方法結(jié)束后i變量仍然存在的原因,還有一點(diǎn)需要注意的,外部變量只有一個,如果多個匿名方法捕獲了它,那么這些匿名方法使用的都是一個變量,局部變量則沒有這個問題
循環(huán)中創(chuàng)建的變量,每個委托捕獲到的都是不同的變量
? ?
我們需要牢記的是
- 補(bǔ)獲的是變量,百不是創(chuàng)建委托初值時它的值
- 捕獲的變量生命周期被延長,至少和捕捉它的委托一樣長
- 多個委托可以捕獲同一個變量
- 必要時創(chuàng)建額外的類型來保存捕獲變量
轉(zhuǎn)載于:https://www.cnblogs.com/LiangSW/p/7203843.html
總結(jié)
- 上一篇: 光大圣玛母婴联名信用卡年费多少?年费政策
- 下一篇: 【笔记篇】C#笔记2