Skip to content
AgileLogics
5 min read

Generics

Prerequisites: Collections: list and dictionary

Generics let you write classes and procedures that work with any type while keeping full type checking. List(Of T) is generic; you can write your own.

Generic procedures

Module Program
    Function FirstOrFallback(Of T)(items As IList(Of T), fallback As T) As T
        If items.Count = 0 Then Return fallback
        Return items(0)
    End Function

    Sub Swap(Of T)(ByRef a As T, ByRef b As T)
        Dim temp = a
        a = b
        b = temp
    End Sub

    Sub Main()
        Console.WriteLine(FirstOrFallback(New List(Of Integer), -1))
        Console.WriteLine(FirstOrFallback({"x", "y"}, "none"))

        Dim p = 1, q = 2
        Swap(p, q)
        Console.WriteLine($"{p} {q}")
    End Sub
End Module
-1
x
2 1

(Of T) declares a type parameter. The compiler usually infers T from the arguments, so you rarely write FirstOrFallback(Of Integer)(...).

Generic classes

Public Class Box(Of T)
    Public ReadOnly Property Value As T

    Public Sub New(value As T)
        Me.Value = value
    End Sub

    Public Function Map(Of TResult)(f As Func(Of T, TResult)) As Box(Of TResult)
        Return New Box(Of TResult)(f(Value))
    End Function
End Class

Module Program
    Sub Main()
        Dim b As New Box(Of Integer)(21)
        Dim doubled = b.Map(Function(x) x * 2)
        Dim text = doubled.Map(Function(x) $"The answer is {x}")
        Console.WriteLine(doubled.Value)
        Console.WriteLine(text.Value)
    End Sub
End Module
42
The answer is 42

Func(Of T, TResult) is a generic delegate type — a function from T to TResult. The next lesson covers lambdas like Function(x) x * 2.

Constraints

Add As to a type parameter to require something of it:

Module Program
    Function Largest(Of T As IComparable(Of T))(items As IEnumerable(Of T)) As T
        Dim best = items.First()
        For Each item In items
            If item.CompareTo(best) > 0 Then best = item
        Next
        Return best
    End Function

    Sub Main()
        Console.WriteLine(Largest({3, 9, 2}))
        Console.WriteLine(Largest({"pear", "apple", "zucchini"}))
    End Sub
End Module
9
zucchini

Common constraints: an interface (As IComparable(Of T)), a base class, As New (has a parameterless constructor), As Class (reference type), and As Structure (value type). Several are written in braces: (Of T As {IComparable(Of T), New}).