簡介: 先看看泛型的概念--“通過參數化類型來實現在同一份代碼上操作多種數據類型。利用“參數化類型”將類型抽象化,從而實現靈活的復用”。 很多初學者在剛開始接觸泛型的時候會比較難理解 “泛型” 在這裡先把 “泛型”當作一個形容詞 這樣比較方便理解 因為很多東西都可以是泛型的 比如-- “泛型的類” ,“泛型的方法”,“泛型的接口”,“泛型的委托” 等...很多時候我們使用泛型可以極大減少代碼重復使程序更加清爽,也可以避免不必要的‘裝箱’ ‘拆箱’過程。 <泛型的引入|為什麼要有泛型?> 在程序設計的過程中我們常常會遇到這樣的情況:為了實現某一個功能我們一開始把方法寫好,但後來我們發現同樣的功能需要我們再寫一次但是這次方法的參數類型和上次不一樣了,這個時候按照敏捷軟件開發的思想,不要過早的進行抽象和應對變化,當變化第一次出現時,使用最快的方法解決它,但變化第二次出現的時,在進行更好的架構設計,這樣的目的是為了避免過度設計,因為有可能第二次變化永遠也不會出現。考慮到功能一樣,所這裡我們通常會直接復制原方法的代碼,然後修改一下參數類型即可快速解決;這樣做確實沒錯,但是有的時候不僅出現了第二次變化 還出現了第三次...或者是更多次變化,繼續使用CV大法修改方法的簽名將會導致大量重復代碼的出現,於是我們就會想,要是存在一個可以傳遞任何數據類型的方法那多好,即把這個方法的實現當成模板 把方法的簽名抽象出來,於是我們引入了泛型。 下面我們來看一下具體的例子: 1.1使用CV大法 ---------------輸入多個 int類型,進行冒泡排序讓它們依次重小到大輸出,代碼如下: 復制代碼 public class SortHelper { public void BubbleSort(int[] arr) { int length = arr.Length; for (int i = 0; i < length-1; i++) { for (int j = 0; j < length-1-i; j++) { if (arr[j]>arr[j+1]) { int temp=arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } } 復制代碼 測試: 復制代碼 static void Main(string[] args) { SortHelper sorter = new SortHelper(); int[] a = { 4,5,1,3,2,8,5,0,2}; sorter.BubbleSort(a); //輸出省略 } 復制代碼 輸出為:0,1,2,2,3,4,5,5,8 ---------------輸入多個 Byte類型,進行冒泡排序讓它們依次重小到大輸出,代碼如下: 這個時候我只要復制一下原來的方法改一下簽名就可以了 復制代碼 public class SortHelper { public void BubbleSort(byte[] arr) { int length = arr.Length; for (int i = 0; i < length-1; i++) { for (int j = 0; j < length-1-i; j++) { if (arr[j]>arr[j+1]) { byte temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } } 復制代碼 這樣做雖然可以,但是往後若要 處理N次各種其他 數據類時就 就要大量重復復制 嚴重影響代碼的簡潔度,而且當功能要擴展時 ,每個方法都要修改,維護起來非常不方便。 1.2使用泛型(泛型類): 我們自然而然的會這樣想了如果可以把方法中的 參數類型 用一個 ”占位符“ 表示 每次 傳入 什麼類型 他就變成什麼類型,這樣就可以將這個方法當成一個模板用了(有點像Web編程中在Html中使用占位符)。 這裡我們用 “T” 來便是這個特殊的參數類型,於是代碼就變成了這樣: 復制代碼 public class SortHelper { public void BubbleSort(T[] arr) { int length = arr.Length; for (int i = 0; i < length-1; i++) { for (int j = 0; j < length-1-i; j++) { if (arr[j]>arr[j+1]) { T temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } } 復制代碼 這裡 T 代表 ”類型的類型“ 和 int ,string ...等數據類型相似,T 就是類型本身。讓人興奮的是真的有像 “T” 這樣的特別存在,在.NET中叫做類型參數. 下面我們看看規范的代碼-- 這裡我們把BubbleSort定義成泛型類 定義泛型類的一種方法是在類後面加上“<T>” 復制代碼 //定義泛型類SortHelper 這裡“where T:IComparable” 是給類型參數T一個限制 -- 參數類型必須實現IComparable接口,否則無法通過編譯 public class SortHelper<T> where T:IComparable { public void BubbleSort(T[] arr) { int length = arr.Length; for (int i = 0; i < length-1; i++) { for (int j = 0; j < length-1-i; j++) { if (arr[j].CompareTo(arr[j+1])>0) { T temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } } 復制代碼 測試: 復制代碼 static void Main(string[] args) { SortHelper<byte> sorter = new SortHelper<byte>(); byte[] a = { 4,5,1,3,2,8,5,0,2}; sorter.BubbleSort(a); SortHelper<int> sorter1 = new SortHelper<int>(); int[] b = { 4, 5, 1, 3, 2, 8, 5, 0, 2 }; sorter1.BubbleSort(b); //輸出省略 } 復制代碼 輸出為: 0,1,2,2,3,4,5,5,8 0,1,2,2,3,4,5,5,8 ---------------輸入多個 自定義類型的實例,進行冒泡排序讓它們依次重小到大輸出,代碼如下: 下面我們來模擬一下寵物店賣的貓 按價格排序 貓類: 復制代碼 public class cat:IComparable { public string name; public int price; public int CompareTo(object obj) { cat catT = (cat)obj; return this.price.CompareTo(catT.price); } public cat(string name, int price) { this.price = price; this.name = name; } } 復制代碼 測試: 復制代碼 static void Main(string[] args) { SortHelper<cat> sorter2 = new SortHelper<cat>(); cat cat1=new cat("貓1",1000); cat cat2=new cat("貓2",1400); cat cat3=new cat("貓3",400); cat[] c = { cat1, cat2, cat3 }; sorter2.BubbleSort(c); //輸出 for (int i = 0; i < c.Length; i++) { Console.WriteLine("Name:"+c[i].name+" Price:"+c[i].price); } }