(翻译)泛型类型介绍

原文:http://en.csharp-online.net/Generic_types

内容:

1、为什么使用泛型?

2、泛型等价

3、专业述语

   3.1、类型参数

   3.2、类型引用

   3.3、开放类型

   3.4、构造类型

   3.5、开放构造类型

   3.6、关闭构造类型

4、基于类型参数的约束

5、泛型类

6、泛型接口

    6.1、定义一个泛型接口

7、泛型委托

 

         为什么使用泛型?

   对于使用泛型,这里主要有两个主要原因来说明一下:

   性能:通过使用装箱和拆箱数据类型来存储对象。这会带来相当大的系统开销,对于性能会带来打击。而通过使用泛型,就会消除这个性能上的问题。

   类型安全:没有一个强类型信息在编译类型可以存储在集合中.为了更好地了解这些,下面有一个没有使用泛型的例子:

         

Code

 

       为了使用这个类,可以将任何对象入栈,然而当检索对象时,需要显示的类型转换.

   

Code

 

       伴随着装箱和拆箱操作会增加性能开销,因为包含有动态内存分配和运行时的类型检测.

       现在猜想会发生什么,如果根据以下代码将一个字符串入栈:

 

Code

 

       代码会被编译,然而直到代码被执行,问题才变得可见,这里会抛出一个InvalidCastException异常.

 

    泛型等价

    如果以上Stack类是一个泛型类型,当将字符串入栈,会产生编译时的错误.如下是Stack类的泛型版本:

 

Code

 

  T是一个参数类型,而在类里面可以将T作为一个类型来使用,它可以代表任何类型,包括一个简单的数据类型int,甚至一个复杂对象car.

  根据以下例子,给出的string作为类型参数T.

 

Code

 

    Stack<string>被称为构造类型,在Stack<string>类型,每一个T的发生代表着类型参数string,Stack<string>的Push和Pop方法操作字符串值,当将其他类型的值入栈,会产生一个编译时错误,剔除显示转换的需要,当它们被检索时,返回它们最初的类型。

    可以使用参数化,不仅用于类,而且还可以用于接口、结构、方法和委托。

   

Code

 

    专业述语

    当谈论泛型时,有若干依据会被使用,因此这值得提及它们,以便当阅读其他文档,可以获得更好的理解.

    类型参数(Type parameters)

    一个类型参数引用在泛型定义中被使用的参数。以上Stack类的泛型版本,这个类接受一个类型参数T。

    类型引用(Type arguments)

    一个类型引用,引用你指定来使用代替类型参数的参数。以下是代码片段,string是类型引用。

  

Code

 

     开放类型

     代替作为一个类而引用,泛型认为Stack<T>作为一个开放类型。这个述语"open"意味着传送一个类型不完全定义的想法,对于采取多种的现实表现是"开发"的。

     构造类型

     一个构造类型代表着一个开放类型的实例。从开放Stack类型来创建一个构造类型。使用下面的代码:

    

Code

 

     或者

 

Code

 

    开放构造类型

    当至少一个类型参数还没有被指定时,一个开放构造类型被创建,参数对于运行时的定义仍然开放。思考下面的类型声明:

 

Code

 

     下面全部是开放构造类型:

 

Code

 

     关闭构造类型

  通过指定所有类型参数来创建关闭构造类型,因此它们对于运行时定义是不开放的。 思考下面的类型声明:

 

Code

   

   下面全部是关闭构造类型:

      

Code

 

       基于参数类型的约束

   约束条件常常限制一个各种类型的泛型类。而客户端代码可以使用它(泛型类)作为类型参数。如果代码尝试使用不受约束的类型来实例化泛型类,结果却导致产生编译错误。约束条件通过where关键字来指定。以下是五种约束类型的表格清单:

   约束条件                      描述

   where T: struct                                          类型参数,T,必需是除了可空类型的任何值类型。

   where T: classs                                        类型参数,T,必需是一个引用类型,包括任何类、接口、委托或者数组类型。

   where T:new()                                            类型参数,T,必需拥有一个公共没有参数的构造函数。当与其他约束条件连合使用,new()约束条件必需最后指定。

   where T : <base class name>                     类型参数,T,必需是派生自指定的基类。

   where T:<interface name>                           类型参数,T,必需实现指定的接口,多个接口约束可以被指定。约束接口也可以是泛型。

   where T:U                                                   类型参数,T,必需是派生自提供U参数。这被称为裸露的类型约束。       

 

         泛型类

   泛型类封装不指定特殊数据类型的操作。泛型类对于其他类可以是基类,因此可以定义若干个虚方法或者抽象方法。任何派生类型必需按照规则遵守,确定泛型抽象的本质流向它。

   如果一个不是泛型的类继承泛型类,派生类必需指定一个类型参数。

   

Code

 

  如果一个泛型基类定义泛型虚方法或者抽象方法,派生类必需通过使用指定的参数类型来覆写泛型方法。

 

Code

 

     一个泛型派生类型可以重新使用自己本身定义的类型占位符.设定在基类的任何约束必需通过派生类型被honoured.

 

Code

 

      伴随着泛型类,它更好使用泛型接口,例如IComparable<T>而不是IComparable,为了逃避值类型的装箱和拆箱.当一个接口在类型参数作为一个约束而被指定.仅仅实现该接口的类型能够使用.例如:

   

Code

 

  定义一个泛型接口

  你可以跟定义泛型类一样来定义泛型接口(包括约束):

  

Code

 

.NET Framework 包括所有通用接口的泛型版本。

泛型委托

假设我们想委托可以更新某一项,但是不确定准备更新哪一项。在这样的情形下,使用

泛型委托是一个最好的选择。为了解释这个概念,以下的代码是基于来自Tod Golding

in .Net 2.0 Generics的一个例子。

假设你将会想象出,我们正在创建一个关于动物,称为猫和狗的软件项目的片段。因此

这里有一些属性和一个ToString()方法的两个类:

 

Code

 

我们认为委托能够更新猫和狗其中一个的年龄。

Code

 

假如我们将会拥有许多动物,采用集合将会是一个不错的办法,而且又能够节省开销,给出一个类型安全的泛型集合将会是最好的选择。

 

Code

 


最后,我们需要两个被委托调用的方法,来更新每个类。以下使用一些代码来进行测试。

 

Code

 

输出结果如下:

posted @ 2008-09-05 21:58  goalbell  阅读(542)  评论(0)    收藏  举报