C# 擴充方法是蠻早期提供的功能,讓指定型別的物件能夠使用額外自訂的方法,將不需要接露的部分隱藏、簡化流程程式碼。
- 擴充方法必須定義在靜態類別內的靜態方法
- 擴充方法至少需要一個參數,參數型別之前必須加上
this
關鍵字
範例
假設系統常使用 decimal
型別,且需要固定轉換成小數位四位,一般是這樣
1 | decimal a = 0.1234567m; |
這樣做沒問題也達到需求,但會有個小缺點,就是整個系統會四處存在這種 hard code,除了不簡潔之外,萬一需求要改成五位,是不是就很麻煩了?
收斂
這種特殊功能的方法其實可以透過靜態類別來處理,例如
1 | public static class DomainConvertHelper |
透過 DomainConvertHelper
這個靜態類別就能夠做統一轉換。實務上不一定是這麼簡單內容,可能會加入 log 或者計時等功能。
這件事能透過擴充方法(extension method)
再次進行簡化,還記得上面說到的,擴充方法使用上必須是靜態類別的靜態方法,同時替第一個參數加上this
關鍵字,接著就能夠在該參數型別透過 .
找到擴充方法的使用了。
1 | public static class ConvertHelper |
擴充方法使用上不需要太擔心,因為是編譯器以及編譯期就處理掉的,有興趣也可以看看IL內容。
其實今天想提這個主題是擴充方法的濫用,上面就是一個最佳的範例!
很多人會覺得這個做沒問題,系統就是很高頻率使用 decimal 轉成 string。
沒錯,但不是所有的 decimal 都有這樣的需求,會變成使用 decimal 型別的人都能夠呼叫 ConvertToF4
此擴充方法,萬一內容與開發者是不預期的就會很麻煩。以上面的例子來延伸討論,細心的人都有注意到程式碼最後我有附上程式產出結果是 0.1235
,就是預設第五位數四捨五入。
如果今天我想要的結果是 0.1234
,開發者誤用了 ConvertToF4
這個方法就會導致結果不預期,因此要極力避免不相關的型別擴充方法,原則很簡單:
- 該型別是不是都需要使用此擴充方法
透過這個原則我們就能夠避免濫用擴充方法在不必要的型別上,而特定 domain 的操作應該還是保留在靜態方法內。