在使用面向?qū)ο蟮恼Z言進行項目開發(fā)的過程中,較多的會使用到“繼承”的特性,但是并非所有的場景都適合使用“繼承”特性,在設(shè)計模式的一些基本原則中也有較多的提到。
繼承的有關(guān)特性的使用所帶來的問題:對象的繼承關(guān)系實在編譯時就定義好了,所以無法在運行時改變從父類繼承的實現(xiàn)。子類的實現(xiàn)與它父類有非常緊密的依賴關(guān)系,以至于父類實現(xiàn)中的任何變化必然會導(dǎo)致子類發(fā)生變化。當你需要復(fù)用子類時,如果繼承下來的實現(xiàn)不適合解決新的問題,則父類必須重寫它或被其他更適合的類替換,這種依賴關(guān)系限制了靈活性并最終限制了復(fù)用性。替代繼承特性的方式,較多的會采用 合成/聚合復(fù)用原則,“合成/聚合復(fù)用原則”:盡量使用合成/聚合,盡量不要使用類繼承。
如果在新類型的對象應(yīng)當攜帶有關(guān)額外行為的細節(jié),在使用繼承特性時,有時可能不太適合,例如:處理指類型,密封類,或者接口時。在面對這些要求時,我們有時候會寫一些靜態(tài)類包含一些靜態(tài)方法。但是過多的靜態(tài)方法會造成額外的不必要的開銷。
一.擴展方法概述:
面對以上的有關(guān)“繼承”的問題,以及在面對項目的一些需求時,我們需要解決這些問題的方式就是“擴展方法”。在C#3.0中引入了“擴展方法”,既有靜態(tài)方法的優(yōu)點,又使調(diào)用它們的代碼的可讀性得到了提高。在使用擴展方法時,可以像調(diào)用實例方法那樣調(diào)用靜態(tài)方法。
1.擴展方法的基本原則:
(1).C#只支持擴展方法,不支持擴展屬性、擴展事件、擴展操作符等。
(2).擴展方法(第一個參數(shù)前面是this的方法)必須在非泛型的靜態(tài)類中聲明,擴展方法必須有一個參數(shù),而且只有第一個參數(shù)使用this標記。
(3).C#編譯器查找靜態(tài)類中的擴展方法時,要求這些靜態(tài)類本身必須具有文件作用域。
(4).C#編譯要求“導(dǎo)入”擴展方法。(靜態(tài)方法可以任意命名,C#編譯器在尋找方法時,需要花費時間進行查找,需要檢查文件作用域中的所有的靜態(tài)類,并掃描它們的所有靜態(tài)方法來查找一個匹配)
(5).多個靜態(tài)類可以定義相同的擴展方法。
(6).用一個擴展方法擴展一個類型時,同時也擴展了派生類型。
2.擴展方法聲明:
(1).必須在一個非嵌套的、非泛型的靜態(tài)類中(所以必須是一個靜態(tài)方法)
(2).至少有一個參數(shù)。
(3).第一個參數(shù)必須附加this關(guān)鍵字做前綴。
(4).第一個參數(shù)不能有其他任何修飾符(如ref或out)。
(5).第一個參數(shù)的類型不能是指針類型。
以上的兩個分類說明中,對擴展方法的基本特性和聲明方式做了一個簡單的介紹,有關(guān)擴展方法的使用方式,會在后面的代碼樣例中進行展示,再次就不再多做說明。
二.擴展方法原理解析:
“擴展方法”是C#獨有的一種方法,在擴展方法中會使用ExtensionAttribute這個attribute。
C#一旦使用this關(guān)鍵字標記了某個靜態(tài)方法的第一個參數(shù),編譯器就會在內(nèi)部向該方法應(yīng)用一個定制的attribute,這個attribute會在最終生成的文件的元數(shù)據(jù)中持久性的存儲下來,此屬性在System.Core dll程序集中。
任何靜態(tài)類只要包含了至少一個擴展方法,它的元數(shù)據(jù)中也會應(yīng)用這個attribute,任何一個程序集包含了至少一個符合上述特點的靜態(tài)類,它的元數(shù)據(jù)也會應(yīng)用這個attribute。如果代碼用了一個不存在的實例方法,編譯器會快速的掃描引用的所有程序集,判斷它們哪些包含了擴展方法,然后,在這個程序集中,可以掃描包含了擴展方法的靜態(tài)類。
如果同一個命名空間中的兩個類含有擴展類型相同的方法,就沒有辦法做到只用其中一個類中的擴展方法。為了通過類型的簡單名稱(沒有命名空間前綴)來使用類型,