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