Generic Procedures in Visual Basic

Универсальная процедура, также называемая универсальным методом, — это процедура, определяемая по крайней мере одним параметром типа. Это позволяет вызывающему коду адаптировать типы данных к его требованиям при каждом вызове процедуры.

Процедура не является универсальной по причине определения внутри универсального класса или универсальной структуры. Чтобы быть универсальным, процедура должна принимать по крайней мере один параметр типа, а также любые обычные параметры, которые могут потребоваться. Универсальный класс или структура могут содержать негенерические процедуры, а негенерический класс, структура или модуль могут содержать универсальные процедуры.

Универсальная процедура может использовать параметры типа в обычном списке параметров, в возвращаемом типе, если он имеет один, и в коде процедуры.

Вывод типа

Вы можете вызвать универсальную процедуру без предоставления аргументов типа вообще. При вызове этого компилятор пытается определить соответствующие типы данных для передачи аргументам типа процедуры. Это называется выводом типов. В следующем коде показан вызов, в котором компилятор вводит тип String в параметр ttype.

Public Sub testSub(Of t)(ByVal arg As t)
End Sub
Public Sub callTestSub()
    testSub("Use this string")
End Sub

Если компилятор не может выводить аргументы типа из контекста вызова, он сообщает об ошибке. Одна из возможных причин такой ошибки — несоответствие ранга массива. Например, предположим, что вы определяете обычный параметр как массив параметра типа. При вызове универсальной процедуры, предоставляющей массив другого ранга (число измерений), несоответствие приводит к сбою вывода типа. В следующем коде показано вызов, в котором двухмерный массив передается в процедуру, которая ожидает одномерный массив.

Public Sub demoSub(Of t)(ByVal arg() As t)
End Sub

Public Sub callDemoSub()
    Dim twoDimensions(,) As Integer
    demoSub(twoDimensions)
End Sub

Вывод типов можно вызывать только путем пропуска всех аргументов типа. Если указать один аргумент типа, необходимо указать их все.

Вывод типов поддерживается только для универсальных процедур. Вы не можете вызвать вывод типов для универсальных классов, структур, интерфейсов или делегатов.

Пример

Description

В следующем примере определяется универсальная Function процедура для поиска определенного элемента в массиве. Он определяет один параметр типа и использует его для создания двух параметров в списке параметров.

Код

Public Function findElement(Of T As IComparable) (
        ByVal searchArray As T(), ByVal searchValue As T) As Integer

    If searchArray.GetLength(0) > 0 Then
        For i As Integer = 0 To searchArray.GetUpperBound(0)
            If searchArray(i).CompareTo(searchValue) = 0 Then Return i
        Next i
    End If

    Return -1
End Function

Комментарии

В предыдущем примере требуется возможность сравнения searchValue с каждым элементом searchArray. Чтобы гарантировать эту возможность, он ограничивает параметр T типа для реализации IComparable<T> интерфейса. Код использует CompareTo метод вместо = оператора, так как не гарантируется, что аргумент типа, предоставленный для T поддержки = оператора.

Процедуру findElement можно протестировать с помощью следующего кода.

Public Sub tryFindElement()
    Dim stringArray() As String = {"abc", "def", "xyz"}
    Dim stringSearch As String = "abc"
    Dim integerArray() As Integer = {7, 8, 9}
    Dim integerSearch As Integer = 8
    Dim dateArray() As Date = {#4/17/1969#, #9/20/1998#, #5/31/2004#}
    Dim dateSearch As Date = Microsoft.VisualBasic.DateAndTime.Today
    MsgBox(CStr(findElement(Of String)(stringArray, stringSearch)))
    MsgBox(CStr(findElement(Of Integer)(integerArray, integerSearch)))
    MsgBox(CStr(findElement(Of Date)(dateArray, dateSearch)))
End Sub

Предыдущие вызовы для MsgBox отображения "0", "1" и "-1" соответственно.

См. также