泛型

    想说泛型,首先说泛型是什么?

      泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码是定义一些可变部分,那部分在使用前必须做出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是对对象,主要引入了类型参数这个概念。——来自百度百科。

    对于百科的解释,比较官方,也不是很好理解,我认为,泛型就是一种不同于集合类型的集合,该集合严格要求数据类型,提高了安全性。(当然这只是我认为,不准确)对比集合类型,使用泛型能够极大的提高集合类型的性能和安全性。避免隐式的装箱和拆箱为了看看使用泛型能为集合类型带来什么好处,先看看不用泛型时集合类型的表现。最典型的非泛型集合类型就是ArrayList了,这里便以它为例做介绍,考虑下面这段代码:

<span style="font-size:18px;"><strong>ArrayList list = new ArrayList();
constintListSize = 3;
for (int i = 0; i <ListSize; i++) {
list.Add(i);     
}
for (int i = 0; i <ListSize; i++) {
int value = (int)list[i];
Console.WriteLine(value);
}</strong></span>
    如果对.NET的类型系统没有深刻的认识,可能会觉得上面的代码没有任何问题。实际上,上面的代码属于典型的“可以运行”的代码,而非“好的”代码。因为ArrayList类型为了包容任何类型,所以它接受的参数为所有类型的基类Object,Object是一个引用类型,而int是一个值类型,因此当调用list.Add(i)时,存在一个装箱操作。同理,当从ArrayList中获得元素时,又需要进行一个拆箱操作:int value = (int)list[i]。这两个操作对于.NET来说是相对耗时的,尤其是当集合类型包含的元素比较多或值类型比较大(比如复杂的枚举或者结构)的时候。通过使用泛型,由于集合中的元素类型在编译时已经确定,就避免了装箱和拆箱的操作,这样便显著地提高了集合类型的性能。在.NET中,与ArrayList作用等同的泛型类型是List<T>,我们可以对它们做一个小小的测试:
<span style="font-size:18px;"><strong>class Program {
constintListSize = 500000;
static void Main(string[] args) {
UseArrayList();
UseGenericList();
Console.ReadKey();
}
private static void UseArrayList() {
ArrayList list = new ArrayList();
longstartTicks = DateTime.Now.Ticks;
for (int i = 0; i <ListSize; i++) {
list.Add(i);
}
for (int i = 0; i <ListSize; i++) {
int value = (int)list[i];
}
longendTicks = DateTime.Now.Ticks;
Console.WriteLine("使用ArrayList,耗时:{0} ticks", endTicks - startTicks);
}
private static void UseGenericList() {
List<int> list = new List<int>();
longstartTicks = DateTime.Now.Ticks;
for (int i = 0; i <ListSize; i++) {
list.Add(i);
}
for (int i = 0; i <ListSize; i++) {
int value = list[i];
}
longendTicks = DateTime.Now.Ticks;
Console.WriteLine("使用List<int>,耗时:{0} ticks", endTicks - startTicks);
}
}</strong></span>
    应该可以看到类似下面的输出:
      使用ArrayList,耗时:468750 ticks
      使用List<int>,耗时:156250 ticks

    根据机器的配置,输出结果差异可能会很大,如果机器比较高档,有可能两个输出都是0,此时可以增大ListSize来获得输出。但不管怎样,可以看到使用List<T>比使用ArrayList提高了差不多3倍的性能。当使用一个大的值类型时,比如枚举或者结构,获得的差异还会更大。


编译时的类型安全(泛型的最大好处,也是编程过程最头疼的地方)

    为什么这么说呢?相信大家在做系统尤其是.NET 版机房时,一定在类型不匹配上出现过很多问题,主要就是在泛型的使用上。常常出现调试失败,某类型无法转换成某类型。当时很头疼吧?其实,这也是泛型的一个优点。这就是类型安全,这是什么意思呢?看下面一段代码:

<span style="font-size:18px;"><strong>ArrayList list = new ArrayList();
int i = 100;
list.Add(i);
string value = (string)list[0];</strong></span>
    有读者一眼就可以看出这段代码有问题,因为类型不匹配,添加到ArrayList中的是一个int类型,而获取时却想将它转换为string类型。可惜的是,编译器无法知道,因为对它来说,不管是int也好,string也好,它们都是Object类型。在编写代码时,编译器提供给开发者的最大帮助之一就是可以检查出错误,也就是常称的编译时错误(Compile time error)。当使用ArrayList时,对于上面的问题,编译器无能为力,因为它认为其是合法的,编译可以顺利通过。这种错误有时候隐藏在程序中很难发现,最糟糕的情况是产品已经交付用户,而当用户在使用时不巧执行到这段代码,便会抛出一个异常,这时的错误,称为运行时错误(Runtime error)。通过使用泛型集合,这种情况将不复存在,当试图进行类似上面的转换时,根本无法通过编译,这样有助于尽早发现问题:
<span style="font-size:18px;"><strong>List<int> list = new List<int>();
int i = 100;
list.Add(i);
string value = (string)list[0];   // 编译错误</strong></span>
    在做机房的时候,就一直想写一篇类似的关于泛型的博客,总结一下所学到的知识,直到前几天,看书看到才突然有感觉写下这篇博客,可能有错误,欢迎读者留言更正。

版权声明:本文为博主原创文章,未经博主允许不得转载。

原文地址:https://www.cnblogs.com/lucari/p/4608564.html