.net泛型通用函数的特殊问题的解决方法

  自从2.0版本的net framework推出之后泛型(Generic)得到了广泛好评。它不必像object类型一样性能上因为“拆箱”或者“装箱”得到损失,同时在编译语法检测阶段就可以实时检测出传入或者传出的类型是否符合特定条件。

  但“金无赤足,人无完人”——在我们享受这些幸福编程的同时,泛型自身类型的不确定也带来了一个显著的问题——无法进行运算符重载。譬如现在我要写一个函数(一个通用的选择排序算法,使用泛型T),该怎么办呢?如果你简单使用这样的代码(C#如下):

复制代码 代码如下:


//从小到大,改进型选择排序算法

public static void Sort<T>(T[] array)
{
     bool flag = false; //标记是否已经排序

for(int i=0;i<array.Length-1;++i)
     {
          flag = false;  //每次假定都已经排序,无须再排序

for(int j=i+1;i<array.Length;++j)
          {
               if(array[i]>array[j])
                {
                      int temp = array[i];
                      array[i]=array[j];
                      array[j]=templ
                      flag = true; //已经排序
                }
          }
           if(!flag)
           {
               break;
           }
     }
}


  编译之后很快发现提示“运算符‘>'无法作用于T”一类的提示。

  为什么呢?我们知道,凡是可以进行大于、小于比较的类型肯定都定义了运算符重载。一般类必须为此定义方可进行比较,不然大于号或者小于号(或者其它运算符)无法知道如何比较而发生错误。那么泛型因为事先都不知道什么类型?编译器检查器自然无法推断你运行时动态传入的这个类型一定保证是实现了运算符重载,严格语法检查情况下就自然报错。

  怎么办呢?强制规定泛型T必须实现比较器(强制T必须实现IComparable,或者类似接口)。

复制代码 代码如下:


public static void Sort<T>(T[] array)where T:IComparable
{
     bool flag = false; //标记是否已经排序

for(int i=0;i<array.Length-1;++i)
     {
          flag = false;  //每次假定都已经排序,无须再排序

for(int j=i+1;i<array.Length;++j)
          {
               if(array[i].Compare(array[j])>0)
                {
                      int temp = array[i];
                      array[i]=array[j];
                      array[j]=templ
                      flag = true; //已经排序
                }
          }
           if(!flag)
           {
               break;
           }
     }
}


  一旦对泛型进行约束,那么泛型必然是实现该接口的类,必然拥有此方法(Compare方法返回结果int类型,如果大于0表示前面一个数字大于后面一个)。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjdwzg.html