C++ Java C#泛型
泛型概述
C#中的泛型
C#泛型和java泛型的比较
C#泛型和C++模板的比较
C#泛型中的约束
泛型概述
Bruce Eckel :您能对泛型做一个快速的介绍么?
Anders Hejlsberg : 泛型其实就是能够向你的类型中加入类型参数的一种能力,也称作参数化的类型或参数多态性。最著名的例子就是List集合类。一个List是一个易于增长的 数组。它有一个排序方法,你可以为 它做索引,等等。现在,如果没有参数化的类型,那么不论使用数组还是使用List都不是很好。如果你使用数组,你能获得强类型,因为你可以声明一个 Customer类型的数组,但你失去了可增长性和那些方便的方法;如果你使用一个List,你能够得到所有的便利,但你失去了强类型。你难以说出一个 List是什么(类型的)List,它只是一个Object的List【译注:“什么类型的List”指的是List存放的元素是什么类型的】。这会给你 带来麻烦 ,因为类型只能在运行形时进行检查,也就是说在编译时不会进行类型检查。就算你硬要把一个Customer放进一个List并试图从中得到一个 String,编译器也不会不高兴。在运行之前你根本无法发现它不能工作。同时,当你将简单类型【译注:指值类型】放入List时,还必须对它们进行装 箱。正是由于这些问题,你不得不在List和数组之间徘徊,你经常要很痛苦地决定应该使用哪一个。
泛型的伟大之处在于你现在可以尽情地享受你的蛋糕了,因为你能够定义一个List(读 作:List of T)【译注:中文可以说成“T类型的List”】。当你使用List时,你居然能够说出它是什么类型的List,并且你将获得强类型,编译器会为你检查它 的类型。这些只是直觉上的好处,它还有其它许多优点。当然,你并不是只能将它用于List,Hastable、Dictionary(将键影射到值上的数 据结构)——所有你想调用的都行。你可能想将String影射到Customer、将int影射到Order,在这些情况下你都能获得强类型。





















































C#泛型中的约束
Bruce Eckel:约束是如何在C#泛型中工作的呢?
Anders Hejlsberg:在C#泛型中,我们能够为类型参数施加约束。以我们的List < T > 为例,你可以说class List < T > where T : IComparable。这意味着T必须实现IComparable接口。
Bruce Eckel:有意思。在C ++ 中,约束是隐式的。
Anders Hejlsberg:是的。在C#中我们也可以这样做。譬如我们有一个Dictionary < K, V > , 它有一个Add()方法,这个方法带有K key和V value参数。Add()方法的实现将希望能够将传递进来的key和Dictionary中已经 存在的key进行比较,而且它希望使用一个称作IComparable的接口。唯一的途径就是将key参数转换为IComparable接口,然后调用 CompareTo方法。当然,当你这么做的时候,你就为K类型和key参数建立了一个隐式的约束。如果传递进来的key没有实现IComparable 接口,你会得到一个运行时错误。这在你的所有方法中都有可能出现,因为你的约定没有要求key必须实现IComparable接口。当然,你还得为运行时 类型检查付出代价,因为你实际上进行了动态类型转换。
使 用约束,你可以消除代码中的动态检查,而在编译时或装载时进行。当你要求K必须实现IComparable接口时,会发生很多事情。对于K类型的值,你现 在可以直接访问接口方法而无需类型转换。因为程序在语义上可以保证它实现了这个接口。无论什么时候你尝试建立这个类型的一个实例时,编译器都会检查这些类 型是否实现了这个接口,如果没有实现,会给你一个编译错误。如果你使用的是反射,你会得到一个异常。
Bruce Eckel:你是说编译器和运行时(都会进行检查)?
Anders Hejlsberg:编译器会检查它,但你仍有可能在运行时通过反射来做这些,因此系统还会检查它。正像我前面说的,编译时可以做的任何事都可以在运行是通过反射来做。
Bruce Eckel:我可以做一个函数模板,换句话说,一个带有不知道类型的参数的函数?你为约束添加了强类型检查,但我是不是能像C ++ 模板那样得到一个弱类型模板? 例如,我能否写一个函数,它带有两个参数A a和B b,并在代码中写a + b?我能不能说我不在乎对于A和B是否有operator + ,因为 它们是弱类型的?
Anders Hejlsberg: 你真正要问的问题应该是这在约束中如何说吧?约束,和其他特性一样,最终将可以是任意复杂的。当你考虑它的时候,约束只是一个模式匹配机制。你可能希望能 够说“这个类型参数必须有一个带有两个参数的构造器、实现了operator + 、有这个静态方法、有那两个实例方法、等等”。问题是,你希望这种模式匹配机制有多复杂?
从 没有任何东西到完全模式匹配是一个整个的连续体。没有任何东西(的模式匹配)太小了,不能说明问题;而完全模式匹配又太复杂了,因此我们需要在中间找一个 平衡点。我们允许你将约束指定为一个类、一个或多个接口,以及一些构造器约束。譬如,你可以说:“这个类型必须实现IFoo和IBar”或“这个类型必须 继承基类X”。一旦你这么做了,在编译时和运行时都会检查这个约束是否为真。这个约束所隐含的任何方法对于类型参数所指定的类型的值都是直接有效的。
现在,在C#中,运算符是静态成员。因此,运算符不能是接口的成员,因此接口约束不能带给你operator +。你只能通过类约束获得operator + ,你可以说这个类型参数必须继承自比如说Number类,并且Number类对于两个Nubmer有operator + 。但你不能抽象地说“必须有一个operator + ”,我们无法知道这句话的具体含义。
Bill Venners:你通过类型进行约束,而不是签名。
Anders Hejlsberg:是的。
Bill Venners:因此这个类型必须扩展一个类或实现一个接口。
Anders Hejlsberg:是的。而且我们还能够走得更远。实际上我们也想过再走远一些,但这会变得相当复杂。而且增加的复杂性与所得到的相比很不值得。如果你想做的事情在约束系统中不直接支持,你可以使用一个工厂模式。例如你有一个Martix < T > , 而在这个Martix(矩阵)中,你可能想定义一个“点乘”【译注:矩阵上的一种乘法运算,另一种称为“叉乘”】方法。这意味着你最终将要考虑如何将两个 T相乘,但你不能将这说成是一个约束,至少当T不是int、double或float时你不能这么说。但你可以让你的Martix带有一个 Calculator < T > 作为参数,而在Calculator < T > 中,有一个称为Multiply的方法。你可以在其中进行实现,并将结果传递给Martix。
Bruce Eckel:而且Calculator也是一个参数化的类型。
Anders Hejlsberg:是的。这有些像工厂模式,还有很多方法可以做到,这也许不是你最喜欢的方法,但做任何事情都要付出代价。
Bruce Eckel: 是呀,我开始认为C ++ 模板是一种弱类型机制。而当你想其中添加了约束后,你从弱类型走向了强类型。但这一定会带来更多的复杂性。这就是代价吧。
Anders Hejlsberg: 关于类型你可以认为它是一个轮盘。这个轮盘放得越高,程序员的日子就会越不好过,但更高的安全性随之而来。但你可以把这个轮盘向任何一个方向转得任意远。
C++ Java C#泛型的更多相关文章
- [改善Java代码]Java的泛型是类型擦除的
泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...
- Java 中泛型的全面解析(转)
Java泛型(generics) 是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在J ...
- Java中泛型 类型擦除
转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ...
- Java 泛型 Java使用泛型的意义
Java 泛型 Java使用泛型的意义 @author ixenos 直接意义 在编译时保证类型安全 根本意义 a) 类型安全问题源自可复用性代码的设计,泛型保证了类型安全的复用模板 b) 使用复用性 ...
- 跟着刚哥梳理java知识点——泛型(十三)
一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: public class GenericTest { public static void main(String[] a ...
- 【Java】泛型学习笔记
参考书籍 <Java核心技术:卷1> 泛型, 先睹为快 先通过一个简单的例子说明下Java中泛型的用法: 泛型的基本形式类似于模板, 通过一个类型参数T, 你可以"私人定制&qu ...
- [转] Java 的泛型擦除和运行时泛型信息获取
原文链接 https://my.oschina.net/lifany/blog/875769 前言 现在很多程序员都会在简历中写上精通 Java.但究竟怎样才算是精通 Java 呢?我觉得不仅要熟练掌 ...
- Java 容器 & 泛型:五、HashMap 和 TreeMap的自白
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Java 容器的文章这次应该是最后一篇了:Java 容器 系列. 今天泥瓦匠聊下 Maps. 一.Ma ...
- 【译】9. Java反射——泛型
原文地址:http://tutorials.jenkov.com/java-reflection/generics.html ===================================== ...
- Java“禁止”泛型数组
Java“禁止”泛型数组 原文:https://blog.csdn.net/yi_Afly/article/details/52058708 1. 泛型定义泛型编程是一种通过参数化的方式将数据处理与数 ...
随机推荐
- 学习1:python输入输出
1. 输出 >>> print "hello world" hello world >>> print 'hello world' hello ...
- linux命令(15):mount/umount命令
使用挂盘之前可以先使用fdisk -l查看硬盘分区情况. 命令格式: mount [-t vfstype] [-o options] device dir -t vfstype 指定文件系统的类型.常 ...
- yum 安装 jdk
https://www.cnblogs.com/kevingrace/p/5870814.html yum -y list java* 以yum库中java-1.7.0为例注:“*”表示将java-1 ...
- LeetCode解题报告—— Word Search & Subsets II & Decode Ways
1. Word Search Given a 2D board and a word, find if the word exists in the grid. The word can be con ...
- 使用GitLab进行落地项目的管理,并且自动更新、重启、回滚
Gitlab 清空项目历史commit,节省空间 http://blog.csdn.net/dounine/article/details/77840416?locationNum=6&f ...
- K8s的内部Pod之间都不通,搞了快两天
试了不亚于二十种方法,绝望的时候,回到了家. 想手工安装,又遇到flannel在手工下,会更改docker启动项的不完善. cni,或许就是k8s的大方向吧. 最后,抱着试一试的态度,将flannel ...
- 【JBPM4】任务form表单
主要是在任务节点处保存一个链接地址(表单),方便在执行到此时取值,访问. 好处是XML可随时修改,部署. JPDL <?xml version="1.0" encoding= ...
- AC日记——大爷的字符串题 洛谷 P3709
大爷的字符串题 思路: 莫队,需开O2,不开50: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 20000 ...
- [js] 数据结构
var dic = {"127.0.0.1":{"1440":[["keyx","keyy","clix&qu ...
- thinkphp 检测上传的图片中是否含有木马脚本
1.检测原理 要想检测图片中是否含有木马脚本,首先从制作原理来分析这种木马程序.这种木马程序是十六进制编码写的,图片的十六进制代码中主要包含<% ( ) %>.<? ( ) ?> ...