• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    .net泛型通用函数的特殊问题的解决方法

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

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

    复制代码 代码如下:

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

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

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

              for(int j=i+1;iarray.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 SortT>(T[] array)where T:IComparable
    {
         bool flag = false; //标记是否已经排序

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

              for(int j=i+1;iarray.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表示前面一个数字大于后面一个)。

      当然,微软类库中有一个Comparer静态类,已经实现了此接口可以直接进行比较(http://msdn.microsoft.com/zh-cn/library/system.collections.comparer.comparer.aspx),因此我们也可以选择直接使用这个静态类中的Compare方法得到结果。

      【例2】实现一个通用的“+”——即如果传入的字符串,则自动按照字符串进行字符拼接;如果传入的是其它基本类型(int,double等),则返回相加结果。

      微软没有为“+”预定义接口,因此无法直接使用接口的方式来做(当然你自己强制定义一个,也可以如法炮制)。我们现在换一个方法——使用表达式树(C#代码如下):

    复制代码 代码如下:

    public static T AddT>(T a, T b)
            {
                Expression left = Expression.Constant(a);
                Expression right = Expression.Constant(b);

                Type t = typeof(T);

                Expression value;

                if (t == typeof(string))
                {
                    value = Expression.Constant(a.ToString()+b.ToString());
                }
                else
                {
                    value = Expression.Add(left, right);
                }

                ExpressionFuncT>> addExp = Expression.LambdaFuncT>>(value);

                FuncT> addFunc = addExp.Compile();

                return addFunc();
            }


      动态判断T是string还是其它基本类型,然后调用不同的方法组合成为表达式树,动态编译成为一个Func表达式,返回结果即可。

    您可能感兴趣的文章:
    • asp.net实现利用反射,泛型,静态方法快速获取表单值到Model的方法
    • 详解.NET 4.0中的泛型协变(covariant)和反变(contravariant)
    • .NET基础之自定义泛型分析
    • .NET开发基础:从简单的例子理解泛型 分享
    • 使用.NET中的Action及Func泛型委托深入剖析
    • .NET CORE动态调用泛型方法详解
    上一篇:在SQL Server中使用CLR调用.NET方法实现思路
    下一篇:spring mvc整合freemarker基于注解方式
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

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