在我們的編程生涯中我們要使用很多很多類庫這些類庫有的是我們自己開發的我們有她的代碼有的是第三方發布的我們不僅沒有他們的代碼連看的機會都沒有
作程序員我們每天都要和BCL(Base Class Linbrary)打交道無疑BCL做為一個年輕的框架類庫她是成功的但是還有一些時候我們還是得寫一些Helper方法來擴展類庫由於我們不能修改類庫的源代碼我們只有寫一個個的靜態類雖然在使用上也算方便但作為追求完美的程序員來說總有些不雅現在我就碰到這樣的事情前兩天奉命寫一個從XML文件加載Chart圖的設置的方法從XML加載數據綁定到對象上這肯定是反射的用武之地了我經常需要寫一些根據對象屬性名字來判斷這個對象是否有這個屬性或者根據屬性名獲取該屬性的值還是按照平常一樣我很快寫了一個PropertyHelper裡面有兩個靜態方法HasPropertyGetValueByName
PropertyHelperHasProperty(point X)如此的調用也還過得去不過在C# 微軟為我們提供了擴展方法現在我們可以直接這樣調用了pointHasProperty(X);看看我是如何實現這個擴展方法的?
publicstaticclassPropertyExtension
{
publicstaticobjectGetValueByName(thisobjectselfstringpropertyName)
{
if(self==null)
{
returnself;
}
Typet=selfGetType();
PropertyInfop=tGetProperty(propertyName);
returnpGetValue(selfnull);
}
}
我給object類型添加了一個擴展方法裡所有的類都繼承自object那所有的類都默認的擁有這個方法了真方便呵呵
注意到和普通的靜態方法有何差別?在這個方法的第一個參數前面多了一個this關鍵字
擴展方法
方法所在的類必須是靜態的
方法也必須是靜態的
方法的第一個參數必須是你要擴展的那個類型比如你要給int擴展一個方法那麼第一個參數就必須是int
在第一個參數前面還需要有一個this關鍵字
按照上面的步驟寫你就得到了一個擴展方法你可以像調用這個類的原生方法那樣去調用它
stringstr=abc;
objectlen=strGetValueByName(Length);
好像string類型現在有了GetValueByName這個方法一樣但實際上string並沒有這樣一個方法那這又是為什麼呢?是我們可愛的編譯器在其中做了手腳為了避開編譯器的干擾我們來直接欣賞MSIL代碼
L_:ldstrLength
L_d:callobjectTestLambdaPropertyExtension::GetValueByName(objectstring)
從MSIL中我們可以看出這段代碼編譯後和調用靜態方法沒有任何的差別(從call指令來看這是在調用一個靜態方法)
從這裡可以知道擴展方法即可以使用實例調用的方式也可以直接使用靜態類調用的方式
strGetValueByName(Length);
PropertyExtensionGetValueByName(strLength);
下面將對擴展方法做一些細節的介紹
Visual Studio 對擴展方法有智能感知的支持如下圖
在方法的圖標上有一個與其他的都不相同他的突變下面還帶有一個藍色的向下的箭頭這就表明這個方法是一個擴展方法
下面是對編寫擴展方法要注意的幾個原則(當然仁者見仁智者見智這也是一家之言)
擴展方法有就近原則也就是如果在你的程序裡有兩個一模一樣的擴展方法一個和你的使用類是處於同一命名空間裡另外一個處於別的命名空間裡這個時候會優先使用同一命名空間裡的擴展方法也就是說血緣關系越近越被青睐
很多人看到擴展方法也許眼裡冒出金光以後在設計的時候不管三七二十一反正可以擴展還有一些人會對類任意擴展將以前一些作為Helper的方法統統使用擴展方法代替注意的是擴展方法有污染性所以我覺得在擴展的時候還是想想是不是值得這樣擴展
在擴展的時候也不要對比較高層的類進行擴展像我上面對object的擴展我覺得就是不可取的object是所有類的基類一經擴展所有的類都被污染了
From:http://tw.wingwit.com/Article/program/net/201311/11425.html