Visual Basic 中的泛型类型 (Visual Basic)Generic Types in Visual Basic (Visual Basic)

泛型类型 是可适应对多种数据类型执行相同功能的单个编程元素。A generic type is a single programming element that adapts to perform the same functionality for a variety of data types. 定义泛型类或过程时,无需为可能需要对其执行该功能的每个数据类型定义单独版本。When you define a generic class or procedure, you do not have to define a separate version for each data type for which you might want to perform that functionality.

就好比是带有可拆卸刀头的螺丝刀。An analogy is a screwdriver set with removable heads. 你检查需要拧动的螺丝,然后选择适合该螺丝的刀头(一字、十字、星形)。You inspect the screw you need to turn and select the correct head for that screw (slotted, crossed, starred). 将正确的刀头插入到螺丝刀柄上后,你就可以使用螺丝刀执行完全相同的功能,即拧螺丝。Once you insert the correct head in the screwdriver handle, you perform the exact same function with the screwdriver, namely turning the screw.

具有不同磁头的平头集的图示。

定义泛型类型时,即使用一个或多个数据类型将其参数化。When you define a generic type, you parameterize it with one or more data types. 这样可允许使用代码定制数据类型以满足其要求。This allows the using code to tailor the data types to its requirements. 代码可以通过泛型元素声明若干个不同的编程元素,每个元素可使用一组不同的数据类型。Your code can declare several different programming elements from the generic element, each one acting on a different set of data types. 但是,无论声明的元素使用哪些数据类型,它们均执行相同的逻辑。But the declared elements all perform the identical logic, no matter what data types they are using.

例如,你可能想创建并使用一个处理特定数据类型(例如 String)的队列类。For example, you might want to create and use a queue class that operates on a specific data type such as String. 可以通过 System.Collections.Generic.Queue<T>声明这样的类,如下例所示。You can declare such a class from System.Collections.Generic.Queue<T>, as the following example shows.

Public stringQ As New System.Collections.Generic.Queue(Of String)

现在,可以使用 stringQ 来专门处理 String 值。You can now use stringQ to work exclusively with String values. 由于 stringQ 专用于 String 而未针对 Object 值进行泛型化,因此,不会有晚期绑定或类型转换。Because stringQ is specific for String instead of being generalized for Object values, you do not have late binding or type conversion. 从而节省了执行时间并减少了运行时错误。This saves execution time and reduces run-time errors.

有关使用泛型类型的更多信息,请参阅 How to: Use a Generic ClassFor more information on using a generic type, see How to: Use a Generic Class.

泛型类的示例。Example of a Generic Class

下面的示例演示了泛型类的主干定义。The following example shows a skeleton definition of a generic class.

Public Class classHolder(Of t)
    Public Sub processNewItem(ByVal newItem As t)
        Dim tempItem As t
        ' Insert code that processes an item of data type t.
    End Sub
End Class

在上面的主干中, t 是一个 类型形参,即你在声明此类时提供的数据类型的占位符。In the preceding skeleton, t is a type parameter, that is, a placeholder for a data type that you supply when you declare the class. 在代码中的其他地方,可以通过为 classHolder 提供不同的数据类型来声明不同版本的 tElsewhere in your code, you can declare various versions of classHolder by supplying various data types for t. 下面的示例演示了两个此类声明。The following example shows two such declarations.

Public integerClass As New classHolder(Of Integer)
Friend stringClass As New classHolder(Of String)

上面的语句声明了 构造类,在这些类中,特定的类型替换了类型形参。The preceding statements declare constructed classes, in which a specific type replaces the type parameter. 此类替换会在构造类中的代码内进行传播。This replacement is propagated throughout the code within the constructed class. 下面的示例显示了 processNewItem 过程在 integerClass中的外观。The following example shows what the processNewItem procedure looks like in integerClass.

Public Sub processNewItem(ByVal newItem As Integer)
    Dim tempItem As Integer
    ' Inserted code now processes an Integer item.
End Sub

有关更完整的示例,请参阅 如何:定义可在不同数据类型上提供相同功能的类For a more complete example, see How to: Define a Class That Can Provide Identical Functionality on Different Data Types.

合格的编程元素Eligible Programming Elements

你可以定义并使用泛型类、结构、接口、过程和委托。You can define and use generic classes, structures, interfaces, procedures, and delegates. 请注意,.NET Framework 定义了几个泛型类、结构和表示常用泛型元素的接口。Note that the .NET Framework defines several generic classes, structures, and interfaces that represent commonly used generic elements. System.Collections.Generic 命名空间提供字典、列表、队列和堆栈。The System.Collections.Generic namespace provides dictionaries, lists, queues, and stacks. 在定义自己的泛型元素之前,请查看 System.Collections.Generic中是否已提供了此元素。Before defining your own generic element, see if it is already available in System.Collections.Generic.

过程不是类型,但可以定义并使用泛型过程。Procedures are not types, but you can define and use generic procedures. 请参阅 Generic Procedures in Visual BasicSee Generic Procedures in Visual Basic.

泛型类型的优点Advantages of Generic Types

泛型类型用作声明几个不同编程元素的基础,而每个元素均处理特定的数据类型。A generic type serves as a basis for declaring several different programming elements, each of which operates on a specific data type. 泛型类型的替代项有:The alternatives to a generic type are:

  1. Object 数据类型进行处理的单一类型。A single type operating on the Object data type.

  2. 一组 特定于类型 的类型版本,每个版本单独进行编码并使用一种特定的数据类型(如 StringInteger )或用户定义的类型(如) customerA set of type-specific versions of the type, each version individually coded and operating on one specific data type such as String, Integer, or a user-defined type such as customer.

与上述替代项相比,泛型类型具有以下优点:A generic type has the following advantages over these alternatives:

  • 类型安全。Type Safety. 泛型类型强制实施编译时类型检查。Generic types enforce compile-time type checking. 而基于 Object 的类型可接受任何数据类型,因此,你必须编写代码以检查是否可接受某种输入数据类型。Types based on Object accept any data type, and you must write code to check whether an input data type is acceptable. 通过泛型类型,编译器可以在运行时之前捕获类型的不匹配。With generic types, the compiler can catch type mismatches before run time.

  • 性能。Performance. 泛型类型无需对数据进行 装箱un装箱 操作,原因是每种泛型类型均专用于一种数据类型。Generic types do not have to box and unbox data, because each one is specialized for one data type. 而基于 Object 的操作必须将输入数据类型进行装箱,以将它们转换为 Object ,而且还将对预定输出的数据进行取消装箱操作。Operations based on Object must box input data types to convert them to Object and unbox data destined for output. 装箱和取消装箱操作会降低性能。Boxing and unboxing reduce performance.

    此外,还要对基于 Object 的类型进行晚期绑定,这意味着需要编写额外的代码才能在运行时访问它们的成员。Types based on Object are also late-bound, which means that accessing their members requires extra code at run time. 这同样会降低性能。This also reduces performance.

  • 代码合并。Code Consolidation. 只能对泛型类型中的代码定义一次。The code in a generic type has to be defined only once. 而一组特定于类型的类型版本必须在每个版本中复制相同的代码,唯一的不同就是该版本的特定数据类型。A set of type-specific versions of a type must replicate the same code in each version, with the only difference being the specific data type for that version. 利用泛型类型,特定于类型的版本全都利用原始的泛型类型生成。With generic types, the type-specific versions are all generated from the original generic type.

  • 代码重用。Code Reuse. 对于不依赖特定数据类型的泛型代码,可以利用不同的数据类型重用它。Code that does not depend on a particular data type can be reused with various data types if it is generic. 你可以经常重用此类代码(甚至利用最初未预料到的数据类型来重用它)。You can often reuse it even with a data type that you did not originally predict.

  • IDE 支持。IDE Support. 在使用通过泛型类型声明的构造类型时,集成开发环境 (IDE) 可以在你开发代码时给予更多的支持。When you use a constructed type declared from a generic type, the integrated development environment (IDE) can give you more support while you are developing your code. 例如,IntelliSense 可以显示适用于构造函数或方法的某个参数的特定于类型的选项。For example, IntelliSense can show you the type-specific options for an argument to a constructor or method.

  • 泛型算法。Generic Algorithms. 独立于类型的抽象算法非常适用于泛型类型。Abstract algorithms that are type-independent are good candidates for generic types. 例如,可以将使用 IComparable 接口对项进行排序的泛型过程用于可实现 IComparable的任何数据类型。For example, a generic procedure that sorts items using the IComparable interface can be used with any data type that implements IComparable.

约束Constraints

虽然泛型类型定义中的代码应尽可能独立于类型,但你可能需要要求向泛型类型提供任何数据类型的某项功能。Although the code in a generic type definition should be as type-independent as possible, you might need to require a certain capability of any data type supplied to your generic type. 例如,如果出于排序或对照的目的而想比较两个项,则它们的数据类型必须实现 IComparable 接口。For example, if you want to compare two items for the purpose of sorting or collating, their data type must implement the IComparable interface. 可通过向类型形参添加 约束 来强制实施此要求。You can enforce this requirement by adding a constraint to the type parameter.

约束的示例Example of a Constraint

下面的示例演示了带有约束(要求类型实参实现 IComparable)的类的主干定义。The following example shows a skeleton definition of a class with a constraint that requires the type argument to implement IComparable.

Public Class itemManager(Of t As IComparable)
    ' Insert code that defines class members.
End Class

如果后续代码尝试从提供未实现 itemManager 的类型的 IComparable中构造一个类,则编译器会提示错误。If subsequent code attempts to construct a class from itemManager supplying a type that does not implement IComparable, the compiler signals an error.

约束的类型Types of Constraints

约束可以按任意组合指定下列要求:Your constraint can specify the following requirements in any combination:

  • 该类型实参必须实现一个或多个接口The type argument must implement one or more interfaces

  • 类型实参至多只能是一个类的类型,或至多只能从一个类继承The type argument must be of the type of, or inherit from, at most one class

  • 对于通过类型实参创建对象的代码,类型实参必须公开一个可供其访问的无参数构造函数The type argument must expose a parameterless constructor accessible to the code that creates objects from it

  • 类型实参必须是 引用类型,或者必须是 值类型The type argument must be a reference type, or it must be a value type

如果需要强制实施多个要求,则可以使用以逗号分隔的 约束列表 (括在大括号 ({ }) 内)。If you need to impose more than one requirement, you use a comma-separated constraint list inside braces ({ }). 若要需要可访问的构造函数,请在列表中包含 New 运算符 关键字。To require an accessible constructor, you include the New Operator keyword in the list. 若需要引用类型,请加入 Class 关键字;若需要值类型,请加入 Structure 关键字。To require a reference type, you include the Class keyword; to require a value type, you include the Structure keyword.

有关约束的详细信息,请参阅 Type ListFor more information on constraints, see Type List.

多个约束的示例Example of Multiple Constraints

下面的示例演示了带有类型形参约束列表的泛型类的主干定义。The following example shows a skeleton definition of a generic class with a constraint list on the type parameter. 在创建此类的实例的代码中,类型实参必须实现 IComparableIDisposable 接口,必须是引用类型,并且必须公开一个可访问的无参数构造函数。In the code that creates an instance of this class, the type argument must implement both the IComparable and IDisposable interfaces, be a reference type, and expose an accessible parameterless constructor.

Public Class thisClass(Of t As {IComparable, IDisposable, Class, New})
    ' Insert code that defines class members.
End Class

重要术语Important Terms

泛型类型引入并使用了以下术语:Generic types introduce and use the following terms:

  • 泛型类型Generic Type. 类、结构、接口、过程或委托的定义,在声明它们时要为它们提供至少一种数据类型。A definition of a class, structure, interface, procedure, or delegate for which you supply at least one data type when you declare it.

  • 类型形参Type Parameter. 在泛型类型定义中,你在声明数据类型时为其提供的占位符。In a generic type definition, a placeholder for a data type you supply when you declare the type.

  • 类型实参Type Argument. 一种特定的数据类型,用于在你通过泛型类型声明构造类型时替换类型形参。A specific data type that replaces a type parameter when you declare a constructed type from a generic type.

  • 约束Constraint. 关于类型形参的条件,用于限制可以为类型形参提供的类型实参。A condition on a type parameter that restricts the type argument you can supply for it. 约束可以要求类型实参必须实现特定接口,必须是特定的类或继承自特定的类,必须具有可访问的无参数构造函数,或者必须是引用类型或值类型。A constraint can require that the type argument must implement a particular interface, be or inherit from a particular class, have an accessible parameterless constructor, or be a reference type or a value type. 你可以组合这些约束,但至多只能指定一个类。You can combine these constraints, but you can specify at most one class.

  • 构造的类型Constructed Type. 通过为泛型类型的类型形参提供类型实参,从泛型类型声明的类、结构、接口、过程或委托。A class, structure, interface, procedure, or delegate declared from a generic type by supplying type arguments for its type parameters.

请参阅See also