Универсальные типы в 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
, отсутствует позднее связывание или преобразование типов. Универсальные типы экономят время выполнения и сокращают ошибки во время выполнения.
Дополнительные сведения об использовании универсального типа см. в разделе Практическое руководство. Использование универсального класса.
Пример универсального класса
В следующем примере показано определение структуры универсального класса.
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 определяет несколько универсальных классов, структур и интерфейсов, представляющих часто используемые универсальные элементы. Пространство имен System.Collections.Generic предоставляет словари, списки, очереди и стеки. Прежде чем определить собственный универсальный элемент, проверьте, уже ли он доступен в System.Collections.Generic.
Процедуры не являются типами, но можно определить и использовать универсальные процедуры. См. универсальные процедуры в Visual Basic.
Преимущества универсальных типов
Универсальный тип служит основой для объявления нескольких различных элементов программирования, каждый из которых работает с определенным типом данных. Альтернативы универсальному типу:
- Один тип, работающий с типом данных
Object
. - Набор версий типа для спецификации. Каждая версия по отдельности закодирована и работает с одним типом данных, например
String
,Integer
или определяемым пользователем типом, напримерcustomer
.
Универсальный тип имеет следующие преимущества по сравнению с этими альтернативами:
- Безопасность типов. Обобщенные типы обеспечивают проверку типов на этапе компиляции. Типы на основе
Object
принимают любой тип данных, и необходимо написать код для проверки допустимости входного типа данных. При использовании универсальных типов компилятор может перехватывать несоответствия типов перед временем выполнения. - Производительность. Универсальные типы не должны упаковывать и распаковывать данные, потому что каждый из них специальным образом оптимизирован для одного типа данных. Операции, основанные на
Object
, должны упаковывать входные типы данных для преобразования их вObject
и распаковывать данные, предназначенные для вывода. Боксинг и анбоксинг снижают производительность. Типы, основанные наObject
, также имеют позднюю привязку, что означает, что для доступа к их членам требуется дополнительный код во время выполнения. Преобразования типов также снижают производительность. - Консолидация кода. Код в универсальном типе должен быть определен только один раз. Набор версий типа должен воспроизводить один и тот же код в каждой версии, при этом единственное отличие заключается в конкретном типе данных для каждой версии. С универсальными типами все версии, относящиеся к конкретному типу, создаются из исходного универсального типа.
- Повторное использование кода. Код, который не зависит от определенного типа данных, можно повторно использовать с различными типами данных, если это универсальный. Вы часто можете повторно использовать его даже с типом данных, который вы изначально не предсказывали.
- Поддержка интегрированной среды разработки. Интегрированная среда разработки (IDE) может обеспечить дополнительную поддержку при создании кода, когда вы используете созданный тип, объявленный из универсального типа. Например, IntelliSense может отображать параметры для конкретного типа аргумента конструктору или методу.
- Универсальные алгоритмы. Абстрактные алгоритмы, независимые от типа, являются хорошими кандидатами для универсальных типов. Например, универсальная процедура, которая сортирует элементы с помощью интерфейса IComparable, можно использовать с любым типом данных, реализующим IComparable.
Ограничения
Хотя код в определении универсального типа должен быть как можно независимо от типа, может потребоваться определенная возможность любого типа данных, предоставленного универсальному типу. Например, если вы хотите сравнить два элемента для сортировки или упорядочивания, их тип данных должен реализовать интерфейс IComparable. Это требование можно применить, добавив ограничение в параметр type.
Пример ограничения
В следующем примере показано определение скелета класса с ограничением, требующим аргумента типа для реализации IComparable.
Public Class itemManager(Of t As IComparable)
' Insert code that defines class members.
End Class
Если последующий код пытается создать класс из itemManager
, предоставив тип, который не реализует IComparable, компилятор сигнализирует об ошибке.
Типы ограничений
Ограничение может указать следующие требования в любом сочетании:
- Аргумент типа должен реализовать один или несколько интерфейсов.
- Аргумент типа должен быть типа одного класса или наследовать не более чем от одного класса.
- Аргумент типа должен предоставлять конструктор без параметров, доступный коду, который создает объекты из него.
- Аргумент типа должен быть ссылочным типомили должен быть типом значения
Код C# может объявить, что аргумент типа должен быть неуправляемым типом. Visual Basic применяет это ограничение для кода Visual Basic, использующего универсальный тип или метод, определенный с этим ограничением (в C#). Однако нельзя объявить ограничение unmanaged
для параметра типа в Visual Basic.
Если вам нужно навязать несколько требований, вы используете список ограничений, разделенных запятыми внутри фигурных скобок ({ }
). Чтобы требовать доступный конструктор, включите в список ключевое слово New Operator. Чтобы требовать ссылочный тип, необходимо включить ключевое слово Class
; чтобы требовать тип значения, необходимо включить ключевое слово Structure
.
Дополнительные сведения об ограничениях см. в списке типов.
Пример нескольких ограничений
В следующем примере показано определение скелета универсального класса со списком ограничений для параметра типа. В коде, который создает экземпляр этого класса, аргумент типа должен реализовать интерфейсы IComparable и IDisposable, быть ссылочным типом и предоставлять конструктор без параметров.
Public Class thisClass(Of t As {IComparable, IDisposable, Class, New})
' Insert code that defines class members.
End Class
Важные термины
Универсальные типы вводят и используют следующие термины:
- универсальный тип. Определение класса, структуры, интерфейса, процедуры или делегата, для которого предоставляется по крайней мере один тип данных при объявлении.
- параметр типа. В определении универсального типа используется параметр, обозначающий тип данных, который вы задаёте при объявлении типа.
- Аргумент типа. Определенный тип данных, который заменяет параметр типа при объявлении конструированного типа из обобщенного типа.
- ограничение. Условие параметра типа, ограничивающего аргумент типа, который можно указать для него. Ограничение может требовать, чтобы аргумент типа реализовал определенный интерфейс, наследуется от определенного класса, имеет доступный конструктор без параметров или является ссылочным типом или типом значения. Эти ограничения можно объединить, но можно указать не более одного базового класса.
- Конструированный тип. Класс, структура, интерфейс, процедура или делегат, объявленный из универсального типа, предоставляя аргументы типа для параметров типа.