首先先感谢MSDN中的一些优秀的外国友人精彩的回答,我从那里也受益良多,写此博文。

  自从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]=templflag = 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]=templflag = 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 Add<T>(T a, T b){Expression left = Expression.Constant(a);Expression right = Expression.Constant(b);Type t = typeof(T);Expression value;if (t is string)){value = Expression.Constant(a.ToString()+b.ToString());}else{value = Expression.Add(left, right);}Expression<Func<T>> addExp = Expression.Lambda<Func<T>>(value);Func<T> addFunc = addExp.Compile();return addFunc();}

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

另外一种思路就是说把泛型T先强制转化成ValueType(检测是否是该类,这里提醒诸位读者——一切基本值类型,包括自定义值类型都是默认继承于ValueType)。然后逐一判断是否是int还是什么其它类型,代码如下(C#):

public static T Add<T>(T a, T b)where T:class{var result1 = a as ValueType;var result2 = b as ValueType;//All can be converted to struct type and do addingif (result1 != null && result2 != null){if(T is int){return ((int)result1 + (int)result2) as T;}//其它各个判断语句……
            }return (a.ToString() + b.ToString()) as T;}

转载于:https://www.cnblogs.com/ServiceboyNew/archive/2013/02/27/2934588.html

泛型通用函数的一些特殊问题的解决方法相关推荐

  1. java fastjson 泛型_解决fastjson泛型转换报错的解决方法

    错误信息 Exception in thread "main" java.lang.ClassCastException: com.alibaba.fastjson.JSONObj ...

  2. 关于excel导入到封装成工具类jar包和web版门店收银网络无法无法连接上的解决方法...

    2011-12-4 1.excel导入工具封装碰到如何给传输过来的泛型对象进行对象点Setter的方法,解决方法应该可以查看struts2框架的源码查看他在拦截器作用下是怎么给action这个类的一个 ...

  3. java中的方法求和_在Java中模拟求和类型的巧妙解决方法

    java中的方法求和 在继续阅读实际文章之前,我想感谢令人敬畏的Javaslang库的作者Daniel Dietrich ,他在我面前有了这个主意: @lukaseder尝试使用静态方法<T,T ...

  4. 在Java中模拟求和类型的巧妙解决方法

    在继续阅读实际文章之前,我想感谢令人敬畏的Javaslang库的作者Daniel Dietrich ,他在我面前有了这个主意: @lukaseder尝试使用静态方法<T,T1扩展T,... Tn ...

  5. 【转】C#中的弱事件:不同的解决方法

    中文原文:http://www.itgrass.com/a/csharp/C-sl/200811/05-8388.html 英文出处:http://www.codeproject.com/KB/cs/ ...

  6. DataBinding 大坑总结(网上我暂时搜不到解决方法)

    在使用多Module中使用DataBinding会引发一些奇怪的问题,最近好好的腾出时间来折腾这些奇怪的问题: 1:如果当Module启动DataBinding重启AS启动报错的话,就启用允许多行代码 ...

  7. mysql 乱码 越南_MySQL_mysql数据库乱码之保存越南文乱码解决方法,我自己测试一下,很多字符变 - phpStudy...

    mysql数据库乱码之保存越南文乱码解决方法 我自己测试一下,很多字符变成了 '?'. 数据库连接已经是使用了 utf8 字符集: define("MYSQL_ENCODE", & ...

  8. kali安装vscode和无法启动解决方法

    一.安装 1)源安装 使用如下命令来增加源: curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > m ...

  9. mysql error number 1130,[转]mysql error number 1130的解决方法

    关键字: is not allowed to connect to this MySQL server 如果你想连接你的mysql的时候发生这个错误: ERROR 1130: Host '192.16 ...

最新文章

  1. matepad和鸿蒙,爆料称华为MatePad 2系列平板有三个版本:预装鸿蒙OS
  2. python3 字典添加_python3字典删除元素和添加元素的几种方法
  3. 如果现在还要设计一个新系统,为什么选择 Kafka 而不是 RabbitMQ?
  4. ipynb是什么文件_数据科学家的神器:为什么大家都用Kaggle?
  5. DSO windowed optimization 代码 (3)
  6. 关于JavaScript中cookie的用法例子
  7. 传销组织生化环材说(正论)
  8. 联通eSIM卡哪些城市可以开通办理
  9. zookeeper 客户端 zkCli.sh 的使用 查看节点
  10. 编辑手机pad端调试方法
  11. Linux初级入门百篇-lsof工具
  12. 计算机睡眠打印机不可用设置,win7系统下打印机属性显示不可用如何解决
  13. java mail类_Java Mail工具类
  14. 台式计算机蓝牙如何安装,台式电脑没有蓝牙怎么安装
  15. selenium+python 的微博自动转赞评功能实现
  16. java中的udp丢包_udp丢包 处理
  17. 分类算法及其应用场景
  18. IDEA自动导包(全局设置)
  19. 全免费 个人电脑部署私有云电脑系统 特别适合初创团队和工作室
  20. 2018 BUPT Winter Training #3 Div.2

热门文章

  1. win10宽带连接断网自动重连
  2. 112. 路径总和 golang
  3. gdb调试常用命令速查(段错误调试)
  4. SPOJ - QTREE3Query on a tree again!——树链剖分
  5. linux socket 编程(C语言)
  6. 【电路原理】学习笔记(1):电路模型的基本变量
  7. UNIX网络编程笔记(7):回射程序的UDP版本
  8. MySQL字段拼接Concat
  9. MySQL 数据还原
  10. 线性代数-矩阵-转置 C和C++的实现