Универсальные типы в 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 Class.For 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 , указав различные типы данных для t.Elsewhere 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 Basic.See 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. Набор версий типа, зависящих от типа , каждая версия по отдельности запрограммирована и работает на одном конкретном типе данных, таком как String , Integer или определяемом пользователем типе, например customer .A 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 operator .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 List.For 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. В коде, который создает экземпляр этого класса, аргумент типа должен реализовывать интерфейсы IComparable и IDisposable , быть ссылочным типом и предоставлять доступ к конструктору без параметров.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