擴展方法使你能夠向現有類型“添加”方法,而無需創建新的派生類型、重新編譯或以其他方式修改原始類型。 擴展方法是一種特殊的靜態方法,但可以像擴展類型上的實例方法一樣進行調用。 以上是msdn官網對擴展方法的描述,現在我通過一個情景例子來對此進行闡釋。假設一個控制台程序class Program{}裡面的主函數如下:
static void Main(string[] args) { DateTime now = DateTime.Now; string time = now.ToString("yyyy-mm-dd hh:mm:ss"); Console.WriteLine(time); Console.ReadKey(); }
假設需求變了,日期的顯示格式要變成"yyyy-mm-dd"這種格式,當然只需要初始化time時按下面寫法改寫即可:
string time = now.ToString("yyyy-mm-dd");
但是如果要改變日期格式的有很多個類呢?每個都要改一次嗎?這樣一旦需求變來變去就忙死人了。傳統的解決方式是封裝一個幫助類,在裡面寫方法,然後供其他類調用。
本例在當前項目模仿添加一個DateHelper類:public class DateHelper{},在類裡面定義方法:
public static string DateToString(DateTime dt) { return dt.ToString("yyyy-mm-dd hh:mm:ss"); }
於是原來的主函數改寫如下:
static void Main(string[] args) { DateTime now = DateTime.Now; string time = DateHelper.DateToString(now); Console.WriteLine(time); Console.ReadKey(); }
此時如果變需求,只需要改寫DateHelp類裡的DateToString()方法就行了,不管有多少個類調用此方法,都會被影響。問題解決了,可是這樣要調用另一個類的方法,還是有點麻煩,有沒有什麼方法能夠讓我們像now.DateToString()一樣直接調用呢?當然DateTime是微軟寫好的,我們改不了,無法創建想要的實例方法,於是,便引出了擴展方法。
下面是擴展方法的要素:
1.此方法必須是一個靜態方法
2.此方法必須放在靜態類中
3.此方法的第一個參數必須以this開頭,並且指定此方法是擴展自哪個類型
根據以上要素,我們DateHelper類改成靜態類:public static class DateHelper{} ,同時改寫DateToString()方法:
public static string DateToString(this DateTime dt) { return dt.ToString("yyyy-mm-dd hh:mm:ss"); }
此時回到主函數方法體,輸入"now."便可以看見自動提示有個DateToString()方法,於是代碼可以這樣寫:
static void Main(string[] args) { DateTime now = DateTime.Now; string time = now.DateToString(); Console.WriteLine(time); Console.ReadKey(); }
顯而易見,這樣用起來會更加便捷,而且這樣讓我們看起來確實就像是被擴展類型本身具有的實例方法一樣,可讀性很高。下面概括一下擴展方法的特點:
1.擴展方法擴展自哪個類型,就必須是此類型的變量來使用,其他類型無法使用,本例擴展自DateTime類型,就只能是被DateTime類型的變量.出來(now.DateToString())
2.擴展方法中的this後面的參數不屬於方法的參數,本例是無參數,this後面的DateTime dt是指明擴展方法擴展自何種類型
3.如果擴展方法和實例方法具有相同的簽名,則優先調用實例方法
4.擴展自父類上的方法,可以被子類的對象直接使用
5.擴展自接口上的方法,可以被實現類的對象直接使用
6.擴展方法最終還是被編譯器編譯成:靜態類.靜態方法(),本例中now.DateToString()最終還是會被編譯成DateHelper.DateToString(now),這是它的本質
實際上,我們可能會遇到這樣的情景,如在接口擴展一個方法的時候,所有的原本已實現該接口的類都要實現新擴展的方法,這樣的改動是一個很麻煩的工作,可以使用擴展方法“曲線救國”;而有時候我們想為某個類添加新方法卻不想改動這個類,那麼擴展方法這種“偽添加”方法的方式就體現出它的價值了。最常見的擴展方法是LINQ標准查詢運算符,運用廣泛,這種方便快捷的方式理應博得碼農們點1024個贊。
&可以作為“按位與”或是“取地址”運算符
下面是作為兩種用法的介紹:
1. 按位與運算 按位與運算符"&"是雙目運算符。其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為1時,結果位才為1 ,否則為0。參與運算的數以補碼方式出現。
例如:9&5可寫算式如下: 00001001 (9的二進制補碼)&00000101 (5的二進制補碼) 00000001 (1的二進制補碼)可見9&5=1。
按位與運算通常用來對某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 運算 ( 255 的二進制數為0000000011111111)。
2.取地址
&作為一元運算符,結果是右操作對象的地址。
例如&x返回x的地址。
地址本身是一個抽象的概念,用於表示對象在存儲器中的邏輯位置
&可以作為“按位與”或是“取地址”運算符
下面是作為兩種用法的介紹:
1. 按位與運算 按位與運算符"&"是雙目運算符。其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為1時,結果位才為1 ,否則為0。參與運算的數以補碼方式出現。
例如:9&5可寫算式如下: 00001001 (9的二進制補碼)&00000101 (5的二進制補碼) 00000001 (1的二進制補碼)可見9&5=1。
按位與運算通常用來對某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 運算 ( 255 的二進制數為0000000011111111)。
2.取地址
&作為一元運算符,結果是右操作對象的地址。
例如&x返回x的地址。
地址本身是一個抽象的概念,用於表示對象在存儲器中的邏輯位置