Generic Procedures in Visual Basic
Una routine generica, detta anche metodo generico, è una routine definita con almeno un parametro di tipo. In questo modo il codice chiamante può adattare i tipi di dati ai relativi requisiti ogni volta che chiama la routine.
Una routine non è generica semplicemente per il fatto di essere definita all'interno di una classe generica o di una struttura generica. Per essere generica, la routine deve accettare almeno un parametro di tipo, oltre a qualsiasi parametro normale che potrebbe accettare. Una classe o una struttura generica può contenere routine non generiche e una classe, una struttura o un modulo non generici possono contenere routine generiche.
Una routine generica può usare i parametri di tipo nell'elenco dei parametri normali, nel tipo restituito, se presente, e nel codice della routine.
Inferenza di tipi
È possibile chiamare una routine generica senza fornire argomenti tipo. Se viene chiamata in questo modo, il compilatore tenta di determinare i tipi di dati appropriati da passare agli argomenti tipo della routine. Questo processo è detto inferenza del tipo. Nel codice seguente viene illustrata una chiamata in cui il compilatore deduce che deve passare il tipo String
al parametro di tipo t
.
Public Sub testSub(Of t)(ByVal arg As t)
End Sub
Public Sub callTestSub()
testSub("Use this string")
End Sub
Se il compilatore non riesce a dedurre gli argomenti tipo dal contesto della chiamata, segnala un errore. Una possibile causa di un errore di questo tipo è una mancata corrispondenza della classificazione della matrice. Si supponga, ad esempio, di definire un parametro normale come matrice di un parametro di tipo. Se si chiama la routine generica fornendo una matrice di una classificazione diversa (numero di dimensioni), la mancata corrispondenza causa l'esito negativo dell'inferenza del tipo. Il codice seguente illustra una chiamata in cui viene passata una matrice bidimensionale a una routine che prevede una matrice unidimensionale.
Public Sub demoSub(Of t)(ByVal arg() As t)
End Sub
Public Sub callDemoSub()
Dim twoDimensions(,) As Integer
demoSub(twoDimensions)
End Sub
È possibile richiamare l'inferenza del tipo solo omettendo tutti gli argomenti tipo. Se si fornisce un argomento tipo, è necessario fornirli tutti.
L'inferenza del tipo è supportata solo per le routine generiche. Non è possibile richiamare l'inferenza del tipo su classi, strutture, interfacce o delegati generici.
Esempio
Descrizione
Nell'esempio seguente viene definita una routine generica Function
per trovare un particolare elemento in una matrice. Viene definito un parametro di tipo che viene usato per costruire i due parametri nell'elenco dei parametri.
Codice
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
Commenti
L'esempio precedente richiede la possibilità di confrontare searchValue
con ogni elemento di searchArray
. Per garantire questa possibilità, vincola il parametro di tipo T
per implementare l'interfaccia IComparable<T>. Il codice usa il metodo CompareTo anziché l'operatore =
, perché non esiste alcuna garanzia che un argomento tipo fornito per T
supporti l'operatore =
.
È possibile testare la routine findElement
con il codice seguente.
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
Le chiamate precedenti a MsgBox
visualizzano rispettivamente "0", "1" e "-1".