首页 > 代码库 > 面向对象设计——“泛型”的起步

面向对象设计——“泛型”的起步

        泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能。泛型将类型参数的概念引入 .NET Framework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候。例如,通过使用泛型类型参数 T,您可以编写其他客户端代码能够使用的单个类,而不致引入运行时强制转换或装箱操作的成本或风险。

——MSDN


        我的计算机是以Visual Basic 6.0拉开帷幕的,让我印象比较深的是两个排序:选择排序和冒泡排序。当然本文不是来讨论这两个排序的具体实现,更不讨论区别。那要干吗呢?请往下看。
        对于选择排序,完成从小到大的排序,我们要怎么实现功能呢?对于当时的我,肯定毫不犹豫的写出下面的代码,因为课本中就是这样的实现思路:

    public class SelectionSort
    {
        public void Sort(int[] array)
        {
            int length = array.Length;

            for (int i = 0; i < length - 1; i++)
            {
                for (int j = i + 1; j < length; j++)
                {
                    // 对两个元素进行交换
                    if (array[i] > array[j])
                    {
                        int temp = array[i];
                        array[i] = array[j];
                        array[j] = temp;
                    }
                }
            }
        }
    }
        我们来测试一下:
        static void Main(string[] args)
        {
            SelectionSort sorter = new SelectionSort();
            int[] array = { 5, 2, 0, 1, 3, 1, 4 };
            sorter.Sort(array);
            foreach (int i in array) Console.Write(i + " ");
            Console.WriteLine();
            Console.Read();
        }
        输出结果:0 1 1 2 3 4 5
        很不错,比较容易实现了功能。再看看上面的代码,我们实现的是对int类型数据的排序,如果我们换成byte该怎么弄呢?对于VB6.0中,他们是完全兼容的,因为VB6.0能够自动进行隐式转换,但C#是一个强类型的语言,无法在一个接受int数组类型的地方传入一个byte数组。其实也不难,我们只需要复制一下代码,然后改一下参数类型就OK了:
    public class SelectionSort
    {
        public void Sort(byte[] array)
        {
            int length = array.Length;

            for (int i = 0; i < length - 1; i++)
            {
                for (int j = i + 1; j < length; j++)
                {
                    // 对两个元素进行交换
                    if (array[i] > array[j])
                    {
                        byte temp = array[i];
                        array[i] = array[j];
                        array[j] = temp;
                    }
                }
            }
        }
    }
        不能高兴的太早,现在又有新需求了,需要对一个char类型的数据进行排序,当然我们可以继续按照上面的思路,采用复制粘贴,然后改一下数据类型。这里就不写代码了!
        我们仔细地对比这几个实现方法,会发现方法的实现完全一样,除了方法的签名不同以外,没有任何的区别。但是完成这三个功能,代码的重复度、代码的冗余相当大,对于编程这可是不好味道。那么有没有一种机制,或者说有这样一个关键字,来代替任何类型呢?我们假设有这样一个关系字叫“T”:
    public class SelectionSort
    {
        public void Sort(T[] array)
        {
            int length = array.Length;

            for (int i = 0; i < length - 1; i++)
            {
                for (int j = i + 1; j < length; j++)
                {
                    // 对两个元素进行交换
                    if (array[i] < array[j])
                    {
                        T temp = array[i];
                        array[i] = array[j];
                        array[j] = temp;
                    }
                }
            }
        }
    }
        啊,这效果看起来怎一个“爽”字了得。当然上面的代码是错误的,C#会报错的。到现在,也用不着卖乖了,C#已经帮我们实现了这种效果,那就是泛型。在.Net中,实现比较的基本方法是实现IComparable接口:
    public class SelectionSort
    {
        public void Sort<T>(T[] array) where T : IComparable
        {
            int length = array.Length;
            for (int i = 0; i < length - 1; i++)
            {
                T min = array[i];
                int minIndex = i;
                for (int j = i + 1; j < length; j++)
                {
                    if (min.CompareTo(array[j]) > 0)
                    {
                        min = array[j];
                        minIndex = j;
                    }
                }
                if (minIndex != i)
                {
                    array[minIndex] = array[i];
                    array[i] = min;
                }
            }
        }
    }

        这是泛型的一个最典型的应用,可以看到,通过使用泛型,我们极大地减少了重复代码,使我们的程序更加清爽,泛型类就类似于一个模板,可以在需要时为这个模板传入任何我们需要的类型。