在java中沒有這樣的東西,一個類一旦是 final的 ,這個類就不能再被添加方法, 但是C#能夠做到,可以給 sealed 類添加新的方法,這點我還是比較喜歡c#的。 這就是C#中的擴展方法。 那麼什麼情況下我們才需要去給一個類寫擴展方法呢? 系統自帶的類型,我們無法去修改; 修改源代碼需要較大的... ...
在java中沒有這樣的東西,一個類一旦是 final的 ,這個類就不能再被添加方法, 但是C#能夠做到,可以給 sealed 類添加新的方法,這點我還是比較喜歡c#的。
這就是C#中的擴展方法。
那麼什麼情況下我們才需要去給一個類寫擴展方法呢?
- 系統自帶的類型,我們無法去修改;
- 修改源代碼需要較大的精力,而且可能會帶來錯誤;
- 我們只是需要一個或者較少的幾個方法,修改源代碼費時費力;
- 被擴展的類是sealed的,不能被繼承;(就算不是sealed的,我們也不能因為需要一個方法而去寫一個子類,這樣不是面向對象)
下麵是擴展方法的三個要素:(也算是語法規則)
- 擴展方法必須處於一個靜態類中;
- 擴展方法必須是一個靜態方法;
- 擴展方法的參數列表必須以 this 開頭,this 後面緊跟的是被擴展類,然後才是方法需要的參數;
下麵就舉一個慄子:
我們一般將字元串類型的數字轉換為int類型,一般都是用的 int.Parse() 方法,或者 Convert類的方法,我們能不能給 string 類型添加一個 Parse方法呢?
當然是可以的,代碼上來先:(這裡只寫了無參數的擴展方法,有參數的直接在參數列表中添加即可,調用時傳遞對應參數)
using System; namespace ConsoleApplicationTest { public static class stringExtensionMethod { public static int Parse(this string str) { return int.Parse(str); } } class Program { static void Main(string[] args) { string str = "111"; int i = str.Parse(); Console.WriteLine("i: " + i); } } }有一點可能不好理解,為什麼參數列表裡面有參數,但是在調用的時候卻不傳遞參數,對於這點我之前也是有點迷糊,但是想通了就好了,那裡不是有個 this 關鍵字嗎?this指代的就是當前對象嘛, 也就是被擴展類的實例,也就是擴展方法的調用者,既然是調用者,那還把它當參數傳,肯定不傳呀。
下麵寫一下擴展方法的特點:
- this關鍵字緊跟著的不是參數,而是調用者,調用者後面的參數才是擴展方法真正的參數,在調用時必須傳遞;
- 如果被擴展的類中的實例方法和擴展方法的方法簽名相同(擴展方法中方法的簽名應該要去掉this和調用者參數),則優先調用本類中的實例方法;
- 被擴展類(可以是普通類,也可以是介面抽象類)的子類對象可以直接調用父類的擴展方法,也就是說子類也繼承了父類的擴展方法;
- 這點算是第 3 點的補充,只有被擴展類的本類對象或者子類對象,才能調用擴展方法;