C#中的泛型-1
在软件这个行业,做的越久,往往会觉得很多技术问题最终会偏向数据结构和算法。
记得曾经大学的一堂课上,老师讲了一个关于冒泡排序的算法,下面是课本上的标准实现。
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了,但是编译后发现错误,这是下一次要讨论的问题~