敬业的IT人 >> 编程开发 >> .Net技术 >> .NET Framework 中的泛型概述

.NET Framework 中的泛型概述

敬业的IT人 互联网 佚名 2008-5-23 21:00:13

本主题提供 .NET Framework 和公共语言运行库中泛型的以下功能的概述:

  • 泛型类型和方法的摘要以及讨论这两者的术语。

  • System.Collections.GenericSystem.Collections.ObjectModel 命名空间中的泛型集合类。

  • 其他泛型类型。

  • 转换、搜索谓词以及要对数组或集合的元素进行的操作的泛型委托。

  • 提供泛型类型族通用的功能的泛型接口。

什么是泛型,如何使用和定义泛型

泛型是具有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的对象的类型的占位符;类型参数作为其字段的类型和其方法的参数类型出现。泛型方法可以将其类型参数用作其返回值的类型或者其形参的类型之一。下面的代码阐释一个简单的泛型类定义。

Visual Basic  CopyCode image复制代码 Public Class Generic(Of T) Public Field As T End Class C#  CopyCode image复制代码 public class Generic<T> { public T Field; } C++  CopyCode image复制代码 generic<typename T> public ref class Generic { public: T Field; };

在创建泛型类的实例时,会指定实际类型来替换类型参数。这会建立一个新的泛型类,称为构造泛型类,选定的类型将替换所有出现的类型参数。最后得到按照您选择的类型定制的类型安全的类,如下面的代码所示。

Visual Basic  CopyCode image复制代码 Dim g As New Generic(Of String) g.Field = "A string" C#  CopyCode image复制代码 Generic<string> g = new Generic<string>(); g.Field = "A string"; C++  CopyCode image复制代码 Generic<String^>^ g = gcnew Generic<String^>(); g->Field = "A string";

下面的术语用于讨论 .NET Framework 中的泛型

  • 泛型类型定义”是用作模板的类、结构或接口声明,其中具有该类、结构或接口声明可以包含或使用的类型的占位符。例如,Dictionary 类可以包含两种类型:键和值。因为它只是一个模板,您不能创建作为泛型类型定义的类、结构或接口的实例。

  • 泛型类型参数”或称“类型参数”是泛型类型或方法定义中的占位符。Dictionary 泛型类型具有两个类型参数:TKeyTValue,分别表示其键和值的类型。

  • “构造泛型类型”或称“构造类型”是为泛型类型定义的泛型类型参数指定类型得到的结果。

  • 泛型类型参数”是替换泛型类型参数的任何类型。

  • 一般术语“泛型类型”包括构造类型和泛型类型定义。

  • “约束”是加在泛型类型参数上的限制。例如,可以将类型参数限制为实现 IComparer 泛型接口的类型以确保可以对该类型的实例进行排序。还可以将类型参数限制为具有特定基类的类型、具有默认构造函数的类型或是引用类型或值类型。泛型类型的用户不能替换不满足这些约束的类型参数。

  • 泛型方法定义”是具有两个参数列表的方法:一个泛型类型参数列表和一个形参列表。类型参数可以作为返回类型或形参的类型出现,如下面的代码所示。

    Visual Basic  CopyCode image复制代码 Function Generic(Of T)(ByVal arg As T) As T Dim temp As T = arg ... End Function

    C#  CopyCode image复制代码 T Generic<T>(T arg) { T temp = arg; ...}

    C++  CopyCode image复制代码 generic<typename T> T Generic(T arg) { T temp = arg; ...};

    泛型方法可以出现在泛型或非泛型类型上。需要注意的是,并不是只要方法属于泛型类型,或者甚至是方法的形参的类型是封闭类型的泛型参数,就可以说方法是泛型方法。只有当方法具有它自己的类型参数列表时,才能称其为泛型方法。在下面的代码中,只有方法 G泛型方法。

    Visual Basic  CopyCode image复制代码 Class A Function G(Of T)(ByVal arg As T) As T ... End Function End Class Class Generic(Of T) Function M(ByVal arg As T) As T ... End Function End Class

    C#  CopyCode image复制代码 class A { T G<T>(T arg) {...} } class Generic<T> { T M(T arg) {...} }

    C++  CopyCode image复制代码 ref class A { generic<T> T G(T arg) {...}; }; generic<typename T> ref class Generic { T M(T arg) {...}; };

Visual C++、C# 和 Visual Basic 都提供了对定义和使用泛型的完全支持。有关更多信息,请参见 Visual Basic 中的泛型类型泛型介绍(C# 编程指南)Overview of Generics in C++

嵌套类型和泛型

嵌套于泛型类型中的类型依赖于封闭泛型类型的类型参数,公共语言运行库将这样的嵌套类型视为泛型,即使它们没有自己的泛型类型参数。在创建嵌套类型的实例时,需要为所有封闭泛型类型指定类型参数。

.NET Framework 中的泛型集合

在 .NET Framework 类库中,在 System.Collections.GenericSystem.Collections.ObjectModel 命名空间中提供了很多泛型集合类。有关这些类的更多信息,请参见常用的集合类型。

System.Collections.Generic

许多泛型集合类型是非泛型类型的直接模拟。DictionaryHashtable泛型版本;它使用泛型结构 KeyValuePair 而不是 DictionaryEntry 进行枚举。

ListArrayList泛型版本。存在对应于非泛型 QueueStack 类的泛型版本。

存在 SortedList泛型和非泛型版本,这两个版本都是介于字典和列表之间的混合类型,并且具有相似的性能特点。SortedDictionary 泛型类是提供不同性能特点的纯字典,它没有对应的非泛型类。

LinkedList 泛型类是一个真正的链接列表。它没有对应的非泛型类。

System.Collections.ObjectModel

Collection 泛型类为派生您自己的泛型集合类型提供了基类。ReadOnlyCollection 类为从实现 IList 泛型接口的任何类型生成只读集合提供了简单的方法。KeyedCollection 泛型类提供了存储包含自己键的对象的方法。

其他泛型类型

Nullable 泛型结构允许将值类型视为可以分配为 null 来使用。在使用数据库查询时这非常有用,在数据库查询中可以缺少包含值类型的字段。泛型类型参数可以是任何值类型。

Note注意

在 C# 中不必显式使用 Nullable,因为这种语言具有可空类型的语法。

ArraySegment 泛型结构提供了一种方式来分隔任何类型的一维的、从零开始的数组内的某个范围的元素。泛型类型参数是数组元素的类型。

如果事件遵从 .NET Framework 使用的事件处理模式,则使用 EventHandler 泛型委托可以不必声明委托类型来处理事件。例如,假设您创建了 MyEventArgs 类(该类从 EventArgs 派生)以包含您的事件的数据。然后可以声明事件,如下所示:

Visual Basic  CopyCode image复制代码 Public Event MyEvent As EventHandler(Of MyEventArgs) C#  CopyCode image复制代码 public event EventHandler<MyEventArgs> MyEvent; C++  CopyCode image复制代码 public: event EventHandler<MyEventArgs^>^ MyEvent;

用于操作数组和列表的泛型委托

Action 泛型委托表示对指定类型的元素执行某些操作的方法。可以创建对元素执行所需操作的方法,创建 Action 委托的实例来表示该方法,然后将数组和委托传递给 System.Array.ForEach.Action{ 静态泛型方法。对该数组的每个元素调用该方法。

List 泛型类还提供了一个使用 Action 委托的 ForEach 方法。此方法不是泛型方法。

Note注意

这是泛型类型和方法的有趣的一点。System.Array.ForEach.Action{ 方法必须是静态的(在 Visual Basic 中为 Shared)和泛型的,因为 Array 不是泛型类型;可以指定 System.Array.ForEach.Action{ 操作的类型的唯一原因是该方法具有其自己的类型参数列表。与之相反,非泛型 System.Collections.Generic.List.ForEach(System.Action{ 方法属于泛型List,因此它只是使用它的类的类型参数。该类是强类型的,因此该方法可以是实例方法。

Predicate 泛型委托表示用于确定特定元素是否满足您定义的标准的方法。可以将其与 Array 的下列静态泛型方法一起使用来搜索元素或元素集:ExistsFindFindAllFindIndexFindLastFindLastIndexTrueForAll

Predicate 还可以与 List 泛型类的相应的非泛型实例方法一起使用。

Comparison 泛型委托允许为没有本机排序顺序的数组或列表元素提供排序顺序或者重写本机排序顺序。创建执行比较的方法,创建 Comparison 委托的实例来表示该方法,然后将数组和委托传递给 System.Array.Sort.Comparison{ 静态泛型方法。List 泛型类提供了相应的实例方法重载 System.Collections.Generic.List.Sort(System.Comparison{

Converter 泛型委托允许定义两种类型之间的转换,并允许将一种类型的数组转换为另一种类型的数组,或者将一种类型的列表转换为另一种类型的列表。创建一个将现有列表的元素转换为新类型的方法,创建委托实例来表示该方法,然后使用 System.Array.ConvertAll.Converter{ 泛型静态方法从原数组生成新类型的数组,或者使用 System.Collections.Generic.List.ConvertAll.Converter{ 泛型实例方法从原列表生成新类型的列表。

链接委托

许多使用这些委托的方法返回数组或列表,数组或列表又可以传递给另一个方法。例如,如果您要选择数组的特定元素,将这些元素转换为一种新类型并保存在新数组中,您可以将 FindAll 泛型方法返回的数组传递给 ConvertAll 泛型方法。如果新元素类型缺少自然的排序顺序,则可以将 ConvertAll 泛型方法返回的数组传递给 Sort 泛型方法。

泛型接口

泛型接口为排序和相等比较以及由泛型集合类型共享的功能提供了与非泛型接口对应的类型安全的泛型接口。

相等和排序比较

System 命名空间中,System.IComparableSystem.IEquatable 泛型接口与它们对应的非泛型接口一样,各自定义了用于排序比较和相等比较的方法。类型实现这些接口来提供执行这些比较的能力。

System.Collections.Generic 命名空间中,IComparerIEqualityComparer 泛型接口为没有实现 System.IComparableSystem.IEquatable 泛型接口的类型提供了定义排序比较或相等比较的方式,并为实现了 System.IComparableSystem.IEquatable 泛型接口的类型提供了重新定义这些关系的方式。这些接口由许多泛型集合类的方法和构造函数使用。例如,可以将泛型 IComparer 传递给 SortedDictionary 类的构造函数来为没有实现泛型 System.IComparable 的类型指定排序顺序。存在 System.Array.Sort 泛型静态方法和 System.Collections.Generic.List.Sort(System.Collections.Generic.IComparer{ 实例方法的重载以用于使用泛型 IComparer 实现排序数组和列表。

ComparerEqualityComparer 泛型类为 IComparerIEqualityComparer 泛型接口的实现提供基类,还通过它们各自的 System.Collections.Generic.Comparer.DefaultSystem.Collections.Generic.EqualityComparer.Default 属性提供默认的排序和相等比较。

集合功能

ICollection 泛型接口是泛型集合类型的基本接口。它提供了基本的添加、移除、复制和枚举元素的功能。ICollection泛型 IEnumerable 和非泛型 IEnumerable 继承。

IList 泛型接口使用索引检索的方法扩展 ICollection 泛型接口。

IDictionary 泛型接口使用键控检索的方法扩展 ICollection 泛型接口。.NET Framework 基类库中的泛型字典类型还实现非泛型 IDictionary 接口。

IEnumerable 泛型接口提供泛型枚举数结构。泛型枚举数实现的 IEnumerator 泛型接口继承非泛型 IEnumerator 接口,MoveNextReset 成员(不依赖于类型参数 T)只出现在非泛型接口上。这意味着非泛型接口的任何使用者还可以使用泛型接口。

泛型的限制

下面是 .NET Framework 2.0 版中对泛型的一些限制:

  • 泛型类型可以从大多数基类派生,例如 MarshalByRefObject(可以使用约束来要求泛型类型参数从诸如 MarshalByRefObject 这样的基类派生),但是在此版本中,上下文绑定的泛型类型不受支持。泛型类型可以从 ContextBoundObject 派生,但是尝试创建该类型的实例将导致 TypeLoadException

  • 轻量动态方法不能是泛型方法。有关动态方法的更多信息,请参见反射发出动态方法的情况

  • 在 Visual Basic、C# 和 C++ 中,包含在泛型类型中的嵌套类型不能被实例化,除非已将类型分配给所有封闭类型的类型参数。换句话说就是在反射中,使用这些语言定义的嵌套类型包含其所有封闭类型的类型参数。这样允许在嵌套类型的成员定义中使用封闭类型的类型参数。有关更多信息,请参见 MakeGenericType 中的“嵌套类型”。

    Note注意

    通过在动态程序集中发出代码或通过使用 MSIL 汇编程序 (Ilasm.exe) 定义的嵌套类型不被要求包括其封闭类型的类型参数;但是如果未包括,则这些类型参数也就不在嵌套类的范围中。

    有关更多信息,请参见 MakeGenericType 中的“嵌套类型”。

粤ICP备06119539号
Copyright CiscoSky.Org,Some Rights Reserved.
Email:me1228#tom.com