在軟體這個行業,做的越久,往往會覺得很多技術問題最終會偏向資料結構和演算法。
記得曾經大學的一堂課上,老師講了一個關於氣泡排序的演算法,下面是課本上的標準實現。
1 public class Sort 2 { 3 public void sortArray(int[] arry) 4 { 5 int length = arry.Length; 6 for (int i = 0; i <= length - 2; i++) 7 { 8 for (int j = length - 1; j >= 1; j--) 9 { 10 if (arry[j]<arry[j - 1]) 11 { 12 int temp = arry[j]; 13 arry[j] = arry[j - 1]; 14 arry[j - 1] = temp; 15 } 16 } 17 } 18 } 19 }
當然,就排序本身不是我們這裡要討論的問題。上面的程式碼實現了一個功能:將一組陣列元素按照從大到小的順序排列。
進行簡單的測試
1 static void Main(string[] args) 2 { 3 Sort sor = new Sort(); 4 //建立一個int陣列 5 int[] array = { 8,1,4,7,3}; 6 //排序 7 sor.sortArray(array); 8 //列印排序結果 9 foreach (int i in array) 10 { 11 Console.WriteLine("{0} : ",i); 12 } 13 Console.ReadLine(); 14 }
得到的結果是:
1 3 4 7 8
發現結果ok,心想這就是完美的了。但是不久之後,又需要對一個byte陣列進行排序,而這個程式只接受int型引數,儘管byte的資料範圍是int的子集,但是強型別的C#語言不允許我們在一個接受int的地方傳入byte,不過沒關係,靈機一動,把上面程式碼複製一邊,引數改為byte[]不久好了。
1 public class Sort 2 { 3 public void sortArray(byte[] arry) 4 { 5 int length = arry.Length; 6 for (int i = 0; i <= length - 2; i++) 7 { 8 for (int j = length - 1; j >= 1; j--) 9 { 10 if (arry[j] < arry[j - 1]) 11 { 12 byte temp = arry[j]; 13 arry[j] = arry[j - 1]; 14 arry[j - 1] = temp; 15 } 16 } 17 } 18 } 19 }
以往寫程式碼首先是要實現功能,功能實現了,下一步才是討論如何優化。因為設計之處,大家能夠想到很多很多可能面臨的問題,但實際上有些問題可能永遠不會發生,你卻花費了大量的時間。我囉嗦這句話的意思其實是想告訴大家,不要過早的進行抽象化和應對變化。上面兩個方法已經很好的解決了int和byte的問題,但是新的需求又來了,這一次需要對char型別的陣列進行排序。當然可以繼續copy上面的方法,可是似乎聰明的人不能接受,我們要善於總結歸納,這是曾經上學時我認為學習數學和物理最重要的方法。
對比前面兩個方法,它們除了方法的簽名不同之外完全是一樣的,曾經開發web的時候,在web上生成靜態頁面最常用的一個方式是使用模版,每次生成靜態頁面的時候先載入模版,模版中含有特殊的佔位符,然後從資料庫讀取資料,使用取出的資料替換這些佔位符,最後將模版按照一定的命名規範生成HTML靜態檔案儲存在伺服器上,所以伺服器無需重寫url,只需要把靜態檔案返回給客戶端就好了。
基於這種思路,我們上面的方法可以視為一個模版,而int[],byte[]的位置就使用佔位符來替換掉好了。
於是,把int,byte,char等等都看作是->T,T代表所有型別。
這個時候方法的簽名就是下面這樣了:
public void sort(T[] arry)
但是又有問題了,T怎麼知道自己是誰呢?int,byte還是其他?有人可能想到,通過類的構造方法傳遞T的型別,這裡要說明的是,構造方法接受的引數是型別的例項,而T本身就是型別,顯然無法傳遞它。
public Sort(型別的例項);
.NET專門定義了一種型別傳遞方式
1 public class SortHelper<T> { 2 public void sort(T[] arry) 3 { 4 ...... 5 } 6 }
使用方法:
1 Sort<byte> sort = new Sort<byte>(); 2 byte[] array = {8,1,4,7,3}; 3 sort.sortArray(array);
此時,T知道自己是byte了,但是編譯後發現錯誤,這是下一次要討論的問題~