当前位置:嗨网首页>书籍在线阅读

18-定义泛型方法

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

16.5 定义泛型方法

**本节视频教学录像:3分钟**

我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个用于处理int数据,另一个用于处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为方法的参数类型不同。有没有一种办法,在方法中传入通用的数据类型,这样不就可以合并代码了吗?泛型方法就是专门解决这个问题的。

例如,我们熟悉的冒泡排序(Bubble Sort)算法实现将一个整数数组元素按照从小到大的顺序重新排列的功能。代码如下。

01  public class SortHelper     //实现Bubble Sort算法的类SortHelper
02  {        
03           public void BubbleSort(int [] array) {        
04                   int length = array.Length;        
05                   for (int i=0; i<= length -2;i++) {        
06                          for (int j= length -1; j>=1;j--)        
07                                   if (array[j] < array[j - 1]) {  //交换两个元素
08                                          int temp = array[j];        
09                                          array[j] = array[j - 1];
10                                          array[j - 1] = temp
11                                       }
12                          }
13                   }        
14           }
15  }

上述Bubble Sort算法只能接受一个int类型的数组,如果我们需要对一个byte类型的数组进行排序,只能将Bubble Sort算法代码复制一遍,并将方法的签名作相应改动。代码如下。

01  public class SortHelper        //实现Bubble Sort算法的类SortHelper
02  {        
03           public void BubbleSort(byte [] array) {        
04                   int length = array.Length;        
05                   for (int i=0; i<= length -2;i++) {        
06                          for (int j= length -1; j>=1;j--)        
07                                   if (array[j] < array[j - 1]) 
                                        { //如果前面的元素较大,交换相邻两个元素
08                                          int temp = array[j];        
09                                          array[j] = array[j - 1];
10                                          array[j - 1] = temp
11                                   }
12                  }
13           }        
14  }

然而,当我们下次需要对一个char类型的数组进行排序时,仍然需要将Bubble Sort算法代码复制一遍,并将方法的签名作相应改动。

仔细对比这两个方法,我们会发现除了方法的签名不同以外,这两个方法的实现完全一样。这时就可以将上面的方法体视为一个模板,将它的方法签名视为一个占位符,创建泛型方法来合并这两个方法的功能。

代码如下。

01  public class SortHelper        //实现Bubble Sort算法的类SortHelper
02  {
03           public void BubbleSort <T>(T[] array) where T : IComparable  {        
04                   int length = array.Length;        
05                   for (int i=0; i<= length -2;i++) {        
06                          for (int j= length -1; j>=1;j--)        
07                                   if (array[j].CompareTo(array[j - 1]) < 0) 
                                        {   //如果前面的元素较大,交换相邻两个元素
08                                          int temp = array[j];        
09                                          array[j] = array[j - 1];
10                                          array[j - 1] = temp
11                                   }
12                          }
13           }        
14  }

上述代码中,将方法签名中的参数类型int[]和byte[] 用占位符T[]来代替,并在类名称的后面加了一个尖括号,使用这个尖括号来传递占位符,也就是类型参数。其中“T”可以代表任何类型,这样就屏蔽了两个方法签名的差异。

**提示** 因为“<”和“>”运算符只对数值类型参数有效,要比较两个泛型类型参数值的大小,不能直接用“<”或“>”运算符。解决方法是约束泛型T为“where T : IComparable”,表明泛型T继承自IComparable 接口,可以使用IComparable 接口的CompareTo方法比较大小。

接着就可以像调用普通方法一样调用定义的泛型方法了,唯一的区别是在调用泛型方法时要实例化泛型T。代码如下。

01  class Program        //实现Bubble Sort算法的类SortHelper
02  {        
03           static void Main (string[] args) {        
04           SortHelper sorter = new SortHelper();        
05           int[] array = {8, 2, 4, 6, 10};        
06           sorter.BubbleSort<int>(array);        
07           foreach(int i in array) {   //输出排序结果
08                   Console.Write(“{0 }”,i);        
09          }
10                  Console.WriteLine();
11                  Console.ReadKey();
12          }
13  }

将调用Bubble Sort算法把整型数组array的元素排序,并输出。其中语句:

sorter.BubbleSort<int>(array);

调用泛型方法BubbleSort,并用int实例化T。第一轮编译时,编译器只为SortHelper类型产生“泛型版”的IL代码和元数据,并不进行泛型类型的实例化,“T”在中间只充当占位符。真正的泛型实例化工作以“on-demand”的方式,发生在JIT编译时。JIT编译时,当JIT编译器第一次遇到SortHelper时,将用int类型替换“泛型版”IL代码与元数据中的“T”进行泛型类型的实例化。

泛型方法的泛型参数,可以用在该方法的形参、方法体和返回值三处。上述例子中的泛型方法的泛型参数用在了方法的形参处。