类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候。
使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
关于泛型数据类型中使用的类型的信息可在运行时通过反射获取。
我们事先一个最简单的冒泡排序(Bubble Sort)算法,我们可以是这样实现的:
<span style="font-family:SimSun;font-size:18px;"> public class SortHelper { public void BubbleSort(int[] array) { int length = array.Length; for (int i = 0; i <= length - 2; i++) { for (int j = length - 1; j >= 1; j--) { // 对两个元素进行交换 if (array[j] < array[j - 1]) { int temp = array[j]; array[j] = array[j - 1]; array[j - 1] = temp; } } } } }</span>
测试:
<span style="font-family:SimSun;font-size:18px;"> class Program { static void Main(string[] args) { SortHelper sorter = new SortHelper(); int[] array = { 8, 1, 4, 7, 3 }; sorter.BubbleSort(array); foreach (int i in array) { Console.Write("{0} ", i); } Console.WriteLine(); Console.ReadKey(); } }</span>
我们发现它是可以使用的,而后,我们需要对一个byte类型的数组进行排序,而我们上面的排序算法只能接受一个int类型的数组,尽管我们知道他们是完全兼容的。因为byte类型是int类型的一个自己,但C#是一个强类型的语言,我们无法再一个接受int数组类型的地方传入一个byte数组。
<span style="font-family:SimSun;font-size:18px;">public class SortHelper { public void BubbleSort(int[] array) { int length = array.Length; for (int i = 0; i <= length - 2; i++) { for (int j = length - 1; j >= 1; j--) { // 对两个元素进行交换 if (array[j] < array[j - 1]) { int temp = array[j]; array[j] = array[j - 1]; array[j - 1] = temp; } } } } public void BubbleSort(byte[] array) { int length = array.Length; for (int i = 0; i <= length - 2; i++) { for (int j = length - 1; j >= 1; j--) { // 对两个元素进行交换 if (array[j] < array[j - 1]) { int temp = array[j]; array[j] = array[j - 1]; array[j - 1] = temp; } } } } } </span>
当然,我们需要对一个char类型的数组继续排序,我们当然可以仿照byte类型数组的做法。继续采用复制粘贴,修改一下方法的签名。
我们仔细地对照两个方法,会发现这两个方法的实现完全一样,除了方法的签名不同以外,,没有任何的区别。我们就这样想,我们将上面的方法体现为一个模板,将他的方法签名视为一个占位符,因为它是一个占位符,所以它可以代表任何的类型。我们写出新的代码:
<span style="font-family:SimSun;font-size:18px;"> public class SortHelper3<T> where T:IComparable { public void BubbleSort(T[] array) { int length = array.Length; for (int i = 0; i <= length - 2; i++) { for (int j = length - 1; j >= 1; j--) { // 对两个元素进行交换 if (array[j] < array[j - 1]) { T temp = array[j]; array[j] = array[j - 1]; array[j - 1] = temp; } } } } }</span>
上述的代码编译都通过不了,为什么?举个简单的例子,我们有一个书,书有两个字段:1、int类型ID,2、string类型的Title。我们怎么比较他们的大小呢?因为我们不知道要按照int比还是string进行比较。
我们用代码实现这样问题:
比较的接口:
<span style="font-family:SimSun;font-size:18px;"> public interface IComparable { int CompareTo(object obj); }</span>
<span style="font-family:SimSun;font-size:18px;"> public class Book :IComparable { private int id; private string title; public Book() { } public Book(int id, string title) { this.id = id; this.title = title; } public int Id { get { return id; } set { id = value; } } public string Title { get { return title; } set { title = value; } } public int CompareTo(object obj) { Book book2 = (Book)obj; return this.Id.CompareTo(book2.Id); } }</span>
在这个里面我们用到了CompareTo这个方法中,我们用Id进行比较的,而且,我们可以注意到,我们没有在CompareTo()方法中去比较当前的Book实例的ID与传进来的Book实例的ID,而是将对他们的比较委托给了int类型,因为int类型也实现了IComparable接口。int32类型,实现了CompareTo方法,因此为了获得Book类型,我们需要在方法中进行一个向下强制转换(这个还要好好体会),我们重写SortHelper:
<span style="font-family:SimSun;font-size:18px;"> public class SortHelper3<T> where T : IComparable { public void BubbleSort(T[] array) { int length = array.Length; for (int i = 0; i <= length - 2; i++) { for (int j = length - 1; j >= 1; j--) { // 对两个元素进行交换 if (array[j].CompareTo(array[j - 1]) < 0) { T temp = array[j]; array[j] = array[j - 1]; array[j - 1] = temp; } } } } }</span>
测试:
<span style="font-family:SimSun;font-size:18px;"> static void Main(string[] args) { Book[] bookArray = new Book[2]; Book book1 = new Book(124, ".Net之美"); Book book2 = new Book(45, "C# 3.0揭秘"); bookArray[0] = book1; bookArray[1] = book2; SortHelper3<Book> sorter = new SortHelper3<Book>(); sorter.BubbleSort(bookArray); foreach (Book b in bookArray) { Console.WriteLine("Id:{0}", b.Id); Console.WriteLine("Title:{0}\n", b.Title); } } } </span>
没有问题了。
我们都知道当我们定义一个泛型类的话,该类下面所有的方法都会受到影响,而我们只需要一个防反射杭冕加上类型参数T,这个时候,我们就要想办法吧类型参数T加到方法上,为了降低T作用的范围。
泛型方法的代码这样写:
<span style="font-family:SimSun;font-size:18px;">public class SuperCalculator{ // CODE:其他实现略 public void SpeedSort<T>(T[] array) where T : IComparable { // CODE:实现略 } }</span>
泛型方法的调用可以这样写:
<span style="font-family:SimSun;font-size:18px;">SuperCalculator calculator = new SuperCalculator(); calculator.SpeedSort<Book>(bookArray);</span>
<span style="font-family:SimSun;font-size:18px;">calculator.SpeedSort(bookArray);</span>
我们学习东西的时候,一定要动手去做,才能学到东西,有时候光靠看和想是不行的,我们应该做的是在实践中学会思考。
参考资料:http://www.360doc.com/content/11/1116/11/130258_164743728.shtml