Универсальные типы в Visual Basic (Visual Basic)
Универсальный тип является одиночным элементом программирования, который используется для выполнения одинаковой функциональности для различных типов данных. При определении универсальных классов или процедур не нужно определять отдельную версию для каждого типа данных, для которых может потребоваться выполнение этой функциональности.
В качестве аналогии можно привести отвертку со съемными головками. Вы смотрите на шуруп, который нужно завинтить, и выбираете подходящую головку (шлицевую, крестовую или звездообразную). Меняя головки, вы выполняете с помощью отвертки одну и ту же функцию: завинчиваете или вывинчиваете шуруп.
При определении универсального типа его можно параметризовать с помощью одного или нескольких типов данных. Это позволяет использовать код, чтобы адаптировать типы данных к его требованиям. В коде можно объявить несколько различных элементов программирования из универсального элемента, каждый из которых действует для разных наборов типов данных. Но все объявленные элементы подчиняются одинаковой логике, независимо от того, какие типы данных они используют.
Допустим, вам нужно создать и использовать класс очереди, который работает с определенным типом данных, например String
. Можно объявить такой класс из System.Collections.Generic.Queue<T>, как показано в следующем примере.
Public stringQ As New System.Collections.Generic.Queue(Of String)
Теперь можно использовать stringQ
для работы исключительно со значениями String
. Так как stringQ
предназначен конкретно для String
, а не является универсальным для значений Object
, вам не потребуется позднее связывание или преобразование типа. Это экономит время выполнения и сокращает число ошибок во время выполнения.
Дополнительные сведения об использовании универсального типа см. в разделе How to: Use 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
— это параметр типа, то есть заполнитель для типа данных, указанного при объявлении класса. В другом месте в коде можно объявлять различные версии classHolder
, указав различные типы данных для t
. Два таких объявления показаны в следующем примере.
Public integerClass As New classHolder(Of Integer)
Friend stringClass As New classHolder(Of String)
Предыдущие инструкции объявляют сконструированные классы, в которых указанный тип заменяет параметр типа. Эта замена распространяется по всему коду сконструированного класса. В следующем примере показано, как процедура processNewItem
выглядит в integerClass
.
Public Sub processNewItem(ByVal newItem As Integer)
Dim tempItem As Integer
' Inserted code now processes an Integer item.
End Sub
Более полный пример см. в разделе "Практическое руководство. Определение класса, который может предоставлять идентичные функциональные возможности для разных типов данных".
Допустимые элементы программирования
Можно определять и использовать универсальные классы, структуры, интерфейсы, процедуры и делегаты. Обратите внимание, что платформа .NET Framework определяет несколько универсальных классов, структур и интерфейсов, представляющих часто используемые универсальные элементы. Пространство имен System.Collections.Generic предоставляет словари, списки, очереди и стеки. Перед определением собственного универсального элемента посмотрите, не существует ли он уже в System.Collections.Generic.
Процедуры не являются типами, но можно определять и использовать универсальные процедуры. См. раздел Generic Procedures in Visual Basic.
Преимущества универсальных типов
Универсальный тип служит в качестве основы для объявления нескольких различных программных элементов, каждый из которых работает с определенным типом данных. Альтернативы для универсального типа:
одиночный тип, работающий с типом данных
Object
.Набор типозависимых версий типа; каждая версия кодируется индивидуально и работает с одним конкретным типом данных (например
String
,Integer
) или с определяемым пользователем типом, напримерcustomer
.
Универсальный тип имеет следующие преимущества по сравнению с этими альтернативами.
Безопасность. Универсальные типы обеспечивают проверку типов во время компиляции. Типы на основе
Object
принимают любой тип данных, и необходимо написать код, чтобы проверить, является ли тип входных данных приемлемым. При использовании универсальных типов компилятор может перехватить несоответствие типов до выполнения.Производительность. Универсальные типы не должны упаковывать и распаковывать данные, так как каждый из них является специальным для одного типа данных. Операции, основанные на
Object
, должны упаковывать типы входных данных для их преобразования вObject
и распаковать данные, предназначенные для вывода. Упаковка и распаковка снижают производительность.Типы на основе
Object
имеют позднее связывание, а значит, для доступа к их элементам требуется дополнительный код во время выполнения. Это также снижает производительность.Консолидация кода. Код в универсальном типе должен быть определен только один раз. Набор типозависимых версий типа должен реплицировать тот же код в каждой версии. Единственное отличие состоит в конкретном типе данных для этой версии. При использовании универсальных типов типозависимые версии формируются из исходного универсального типа.
Повторное использование кода. Код, который не зависит от определенного типа данных, можно повторно использовать с различными типами данных, если он является универсальным. Часто его можно повторно использовать даже с типом данных, который изначально не предусматривался.
Поддержка IDE. При использовании сконструированного типа, объявленного из универсального типа, интегрированная среда разработки (IDE) может предоставить дополнительную поддержку при разработке кода. Например, IntelliSense может показать типозависимые параметры аргумента для конструктора или метода.
Универсальные алгоритмы. Абстрактные алгоритмы, которые не зависят от типов, хорошо подходят для универсальных типов. Например, универсальную процедуру, которая сортирует элементы с помощью интерфейса IComparable , можно использовать с любым типом данных, который реализует IComparable.
Ограничения
Несмотря на то, что код в определении универсального типа должен быть максимально независимым от типов, может потребоваться определенная возможность любого типа данных, указанного для универсального типа. Например, если необходимо сравнить два элемента с целью сортировки или упорядочивания, их тип данных должен реализовывать интерфейс IComparable . Соблюдение этого требования можно обеспечить путем добавления ограничения к параметру типа.
Пример ограничения
В следующем примере показано каркасное определение класса с ограничением, которое требует аргумент типа для реализации IComparable.
Public Class itemManager(Of t As IComparable)
' Insert code that defines class members.
End Class
Если последующий код попытается создать класс из itemManager
, используя тип, который не реализует IComparable, компилятор сообщит об ошибке.
Типы ограничений
Ограничение может содержать приведенные ниже требования в любой комбинации.
Аргумент типа должен реализовывать один или несколько интерфейсов.
Аргумент типа должен наследовать только из одного класса или быть типом только одного класса.
Аргумент типа должен предоставлять конструктор без параметров, доступный коду, который создает объекты из него.
Аргумент типа должен быть типом ссылкиили типом значения.
Если нужно задать более одного требования, используйте разделенный запятыми список ограничений , заключенный в фигурные скобки ({ }
). Чтобы требовать конструктор со специальными возможностями, в список будет включен новый оператор ключевое слово. Чтобы требовать ссылочный тип, включите ключевое слово Class
. Чтобы требовать тип значения, включите ключевое слово Structure
.
Дополнительные сведения об ограничениях см. в разделе Type List.
Пример множественных ограничений
В следующем примере показано каркасное определение универсального класса со списком ограничений в параметре типа. В коде, который создает экземпляр этого класса, аргумент типа должен реализовывать интерфейсы IComparable и IDisposable , быть ссылочным типом и предоставлять доступ к конструктору без параметров.
Public Class thisClass(Of t As {IComparable, IDisposable, Class, New})
' Insert code that defines class members.
End Class
Важные термины
Универсальные типы вводят и используют следующие термины.
Универсальный тип. Определение класса, структуры, интерфейса, процедуры или делегата, для которого необходимо указать по крайней мере один тип данных при объявлении.
Параметр типа. В определении универсального типа это заполнитель для типа данных, указываемый при объявлении типа.
Аргумент типа. Определенный тип данных, который заменяет параметр типа при объявлении сконструированного типа из универсального типа.
Ограничение. Условие для параметра типа, ограничивающее аргумент типа, который можно указать для него. Ограничение может требовать, чтобы аргумент типа реализовывал определенный интерфейс, был определенным классом или наследовал от него, имел доступный конструктор без параметров или был ссылочным типом или типом значения. Можно объединять эти ограничения, но невозможно указывать более одного класса.
Сконструированный тип. Класс, структура, интерфейс, процедура или делегат, объявленный из универсального типа с помощью указания аргументов типа для параметров типа.