1.問題提出
有時候,我希望能夠調用一個方法判斷一個string類型是否是合法的郵箱地址字符串。一般的可以採取以下方法:
定義一個專門的靜態工具類,名爲StringFormatChecker,並在其中定義一個方法,名爲CheckMailAddrFormat,用於測試該字符串是否是合法的郵箱地址格式。
public static StringFormatChecker
{
...
//用於測試該字符串是否是合法的郵箱地址格式
public staic bool CheckMailAddrFormat(string str);
...
}
調用時:
...
string str = "Leon.Hong";
bool isValid = StringFormatChecker.CheckMailAddrFormat(str );
//isValid返回false
...
但是這裏有兩個問題:
(1) 對於方法的使用者來說,他除了學習string類外,還增加了瞭解StringFormatChecker類的學習成本
(2) 這個方法不是一個具有良好內聚性的方法,因爲被檢查的資源來源於string,但是卻在另一個類中完成這個過程。
2.利用.Net的擴展方法(extension method)來解決這個問題
首先給出代碼
public static StringFormatChecker
{
...
//用於測試該字符串是否是合法的郵箱地址格式
public staic bool CheckMailAddrFormat(this string str);
...
}
從代碼看,不同之處,僅是對形參加了一個this進行修飾,但是,在調用時,卻可以通過如下形式:
...
string str = "Leon.Hong";
bool isValid = str.CheckMailAddrFormat(str);
//isValid返回false
...
這個其他靜態類的方法貌似變成了一個string的實例方法!!!
COOL&SHOCKING!!!
3.原理簡要分析
(1)在.Net編譯器中,它首先檢查string是否提供了一個CheckMailAddrFormat(string),如果存在這樣的一個實例方法,那麼編譯器就會生成IL來調用它。
(2)如果沒有,則繼續檢查是否任何一個靜態類定義了一個名爲CheckMailAddrFormat(string)的靜態方法,它的第一個參數是和當前用於調用方法的那個表達式的類型匹配的一個類型,而且這個類型必須用this關鍵字標識。同時,它再生成相應的IL代碼來調用。