第12章 泛型

泛型(generic)是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用,即算法重用。

简单的说,开发人员先定义好一个算法,比如排序、搜索、交换、比较或者转换等。但是,定义算法的开发人员并不设定该算法要操作什么数据类型。该算法可以广泛地应用于不同类型的对象。然后,另一个开发人员,只有指定了算法要操作的具体数据类型,就可以开始使用这个现成的算法了。例如,可以用一个排序算法来操作Int32和String等类型对象。

大多数算法都封装在一个类型中,CLR允许创建泛型引用类型和泛型值类型,但不允许创建泛型枚举类型。CLR还允许创建泛型接口和泛型委托。

先来看一个简单的例子,Framework类库中定义了一个泛型列表算法,它知道如何管理一个对象集合。泛型算法没有设定这些对象的数据类型。

封装了泛型列表算法的FCL类称为List<T>。泛型List类的设计者紧接着在这个类名后添加一个<T>,表明它操作的是一个未指定的数据类型。

定义泛型类型时,它为类型指定的任何变量(比如T)都称为类型参数(type parameter)。T是一个变量名,在源代码中能够使用一个数据类型的任何位置,都能使用T。

列如:在List类定义中,

T被用作方法参数,Add方法接收一个T类型的参数public void Add(T item);

T被用作返回值,ToArray方法返回一组T类型的一维数组public T[] ToArray();

根据Microsoft的设计原则,泛型参数变量要么称为T,要么至少以大写T开头(如TKey和TValue)。

使用泛型类型或方法时,指定的具体数据类型称为类型实参(type argument)。

例如:开发人员可指定一个DateTime类型实参来使用List算法。

public class Program{

    private static void SomeMethod()

    {

        //构造一个List来操作DateTime对象

        List<DateTime> dtList = new List<DateTime>();

        //向列表添加DateTime对象,不进行装箱

        dtList.Add(DateTime.Now);

        dtList.Add(DateTime.MinValue);

        //尝试向列表中添加一个String对象,编译时报错,Invalid arguments

        dtList.Add("1/1/2004");

        //从列表提取一个DateTime对象

        DateTime dt = dtList[0];

    }

}

从以上代码可以看出,泛型为开发人员提供了以下优势:

  • 源代码保护à使用一个泛型算法的开发人员不需要访问算法的源代码
  • 类型安全à保证只有与指定具体数据类型兼容的对象才能随同算法使用
  • 更加清晰的代码à DateTime dt = dtList[0];中不需要使用(DateTime)转型将索引器的结果存储在dt变量中
  • 更佳的性能à现在能创建一个泛型算法来操作具体的数据类型,所有值类型的实例都能以传值方式传递,CLR不再需要执行任何装箱操作

12.1 Framework类库中的泛型

泛型最明显的应用就是集合类。

FCL定义的几个泛型集合类,大多数都在System.Collections.Generic和System.Collections.ObjectModel命名空间中。

12.2Wintellect的Power Collections库

12.3泛型基础结构

泛型是在CLR2.0版本中加入的,为了在CLR中加入泛型,Microsoft做了一下工作:

  • 创建新的IL指令,使之能够识别类型实参。
  • 修改现有元数据表的格式,以便表示具有泛型参数的类型名称和方法。
  • 修改各种编程语言,以支持新的语法,允许开发人员定义和引用泛型类型和方法。
  • 修改编译器,使之能生成新的IL指令和修改的元数据格式。
  • 修改JIT编译器,使之能处理新的、支持类型实参的IL指令,以便生成正确的本地代码。
  • 创建新的反射成员,是开发人员能查询类型和成员,以判断它们是否具有泛型参数。
  • 修改调试显示器以显示和修改泛型类型、成员、字段以及局部变量。
  • 修改Visual Studio的智能感知“IntelliSense”。

12.3.1开放类型和封闭成员

 

posted @ 2016-06-26 18:04  Chris_在IT道路上前行  阅读(151)  评论(0编辑  收藏  举报