C#特性 擴(kuò)展方法
作為.net程序員,我們每天都要和BCL(Base Class Linbrary)打交道。無(wú)疑,BCL做為一個(gè)年輕的框架類庫(kù),她是成功的,但是還有一些時(shí)候我們還是得寫一些”Helper”方法來(lái)擴(kuò)展類庫(kù),由于我們不能修改類庫(kù)的源代碼,我們只有寫一個(gè)個(gè)的靜態(tài)類。雖然在使用上也算方便,但作為追求完美的程序員來(lái)說(shuō)總有些不雅。
現(xiàn)在我就碰到這樣的事情,前兩天奉命寫一個(gè)從XML文件加載Chart圖的設(shè)置的方法,從XML加載數(shù)據(jù)綁定到對(duì)象上,這肯定是反射的用武之地了。我經(jīng)常需要寫一些根據(jù)對(duì)象屬性名字來(lái)判斷這個(gè)對(duì)象是否有這個(gè)屬性或者根據(jù)屬性名獲取該屬性的值。還是按照平常一樣,我很快寫了一個(gè)PropertyHelper,里面有兩個(gè)靜態(tài)方法:HasProperty,GetValueByName。
PropertyHelper.HasProperty(point, "X"),如此的調(diào)用也還過(guò)得去,不過(guò)在C# 3.0微軟為我們提供了擴(kuò)展方法?,F(xiàn)在我們可以直接這樣調(diào)用了point.HasProperty(“X”);看看我是如何實(shí)現(xiàn)這個(gè)擴(kuò)展方法的?
public static class PropertyExtension
{
public static object GetValueByName(this object self, string propertyName)
{
if (self == null)
{
return self ;
}
Type t = self.GetType();
PropertyInfo p = t.GetProperty(propertyName);
return p.GetValue(self, null);
}
}
我給object類型添加了一個(gè)擴(kuò)展方法,在.net里所有的類都繼承自object,那所有的類都默認(rèn)的擁有這個(gè)方法了,真方便,呵呵。
注意到和普通的靜態(tài)方法有何差別?在這個(gè)方法的第一個(gè)參數(shù)前面多了一個(gè)this關(guān)鍵字。
擴(kuò)展方法:
1、方法所在的類必須是靜態(tài)的
2、方法也必須是靜態(tài)的
3、方法的第一個(gè)參數(shù)必須是你要擴(kuò)展的那個(gè)類型,比如你要給int擴(kuò)展一個(gè)方法,那么第一個(gè)參數(shù)就必須是int。
4、在第一個(gè)參數(shù)前面還需要有一個(gè)this關(guān)鍵字。
按照上面的步驟寫你就得到了一個(gè)“擴(kuò)展方法”,你可以像調(diào)用這個(gè)類的原生方法那樣去調(diào)用它:
string str = "abc";
object len = str.GetValueByName("Length");
好像string類型現(xiàn)在有了GetValueByName這個(gè)方法一樣,但實(shí)際上string并沒有這樣一個(gè)方法。那這又是為什么呢?是我們可愛的編譯器在其中做了手腳。為了避開編譯器的干擾,我們來(lái)直接欣賞MSIL代碼:
L_0008: ldstr "Length"
L_000d: call object TestLambda.PropertyExtension::GetValueByName(object, string)
從MSIL中我們可以看出,這段代碼編譯后和調(diào)用靜態(tài)方法沒有任何的差別(從call指令來(lái)看,這是在調(diào)用一個(gè)靜態(tài)方法)。
從這里可以知道擴(kuò)展方法即可以使用實(shí)例調(diào)用的方式也可以直接使用靜態(tài)類調(diào)用的方式:
str.GetValueByName("Length");
PropertyExtension.GetValueByName(str,"Length");
下面將對(duì)擴(kuò)展方法做一些細(xì)節(jié)的介紹:
Visual Studio 2008對(duì)擴(kuò)展方法有智能感知的支持,如下圖

在方法的圖標(biāo)上有一個(gè)與其他的都不相同,他的突變下面還帶有一個(gè)藍(lán)色的向下的箭頭,這就表明這個(gè)方法是一個(gè)擴(kuò)展方法。
下面是對(duì)編寫擴(kuò)展方法要注意的幾個(gè)原則(當(dāng)然,仁者見仁、智者見智,這也是一家之言):
擴(kuò)展方法有就近原則,也就是如果在你的程序里有兩個(gè)一模一樣的擴(kuò)展方法,一個(gè)和你的使用類是處于同一命名空間里,另外一個(gè)處于別的命名空間里,這個(gè)時(shí)候會(huì)優(yōu)先使用同一命名空間里的擴(kuò)展方法,也就是說(shuō)“血緣關(guān)系”越近,越被青睞。
很多人看到擴(kuò)展方法也許眼里冒出金光,以后在設(shè)計(jì)的時(shí)候不管三七二十一,反正可以擴(kuò)展。還有一些人會(huì)對(duì)類任意擴(kuò)展,將以前一些作為”Helper”的方法統(tǒng)統(tǒng)使用擴(kuò)展方法代替,注意的是擴(kuò)展方法有“污染性”,所以我覺得在擴(kuò)展的時(shí)候還是想想,是不是值得這樣擴(kuò)展。
在擴(kuò)展的時(shí)候也不要對(duì)比較高層的類進(jìn)行擴(kuò)展,像我上面對(duì)object的擴(kuò)展我覺得就是不可取的,object是所有類的基類,一經(jīng)擴(kuò)展,所有的類都被“污染”了。
發(fā)表與2008-07-16
于2008-08-06第一次更新
相關(guān)文章
C#如何將List<string>轉(zhuǎn)換為L(zhǎng)ist<double>
這篇文章主要介紹了C#如何將List<string>轉(zhuǎn)換為L(zhǎng)ist<double>問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
C#實(shí)現(xiàn)裝箱與拆箱操作簡(jiǎn)單實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)裝箱與拆箱操作,對(duì)于新手理解裝箱與拆箱有一定的幫助,需要的朋友可以參考下2014-07-07
C#中的靜態(tài)字段double.Epsilon實(shí)例詳解
double.Epsilon 是C#中的一個(gè)靜態(tài)字段,表示 double 數(shù)據(jù)類型的最小可表示的正數(shù)值,這篇文章主要介紹了C#中的靜態(tài)字段double.Epsilon的相關(guān)知識(shí),需要的朋友可以參考下2024-01-01
C#中類成員的定義的修飾關(guān)鍵詞知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理了關(guān)于C#中類成員的定義的修飾關(guān)鍵詞知識(shí)點(diǎn)內(nèi)容,有需要的朋友們可以參考下。2020-02-02
C#實(shí)現(xiàn)的字符串相似度對(duì)比類
這篇文章主要介紹了C#實(shí)現(xiàn)的字符串相似度對(duì)比類,本文直接給出類實(shí)現(xiàn)代碼,代碼中包含詳細(xì)注釋,需要的朋友可以參考下2015-07-07
C#實(shí)現(xiàn)將PDF轉(zhuǎn)為線性化PDF
線性化PDF文件是PDF文件的一種特殊格式,可以通過(guò)Internet更快地進(jìn)行查看。這篇文章主要介紹了如何通過(guò)C#實(shí)現(xiàn)將PDF轉(zhuǎn)為線性化PDF,感興趣的小伙伴可以學(xué)習(xí)一下2021-12-12

