Generics in Visual Basic .NET

Imports System
Imports System.Collections.Generic

' As an example of a generic function, SlicesIndex takes
' a list of any comparable type and an element of that
' type and returns the index of the first occurrence of
' v in s, or -1 if not present. The IComparable constraint
' means that we can compare values of this type.
Public Function SlicesIndex(Of T As IComparable)(ByVal s As List(Of T), ByVal v As T) As Integer
    For i As Integer = 0 To s.Count - 1
        If v.CompareTo(s(i)) = 0 Then
            Return i
        End If
    Next
    Return -1
End Function

' As an example of a generic type, List is a
' singly-linked list with values of any type.
Public Class List(Of T)
    Private Class Element
        Public [Next] As Element
        Public Value As T
    End Class

    Private head, tail As Element

    ' We can define methods on generic types just like we
    ' do on regular types, but we have to keep the type
    ' parameters in place. The type is List(Of T), not List.
    Public Sub Push(ByVal v As T)
        If tail Is Nothing Then
            head = New Element With {.Value = v}
            tail = head
        Else
            tail.Next = New Element With {.Value = v}
            tail = tail.Next
        End If
    End Sub

    ' AllElements returns all the List elements as an array.
    Public Function AllElements() As T()
        Dim elems As New List(Of T)()
        Dim e As Element = head
        While e IsNot Nothing
            elems.Add(e.Value)
            e = e.Next
        End While
        Return elems.ToArray()
    End Function
End Class

Module Program
    Sub Main(args As String())
        Dim s As New List(Of String) From {"foo", "bar", "zoo"}

        ' When invoking generic functions, we can often rely
        ' on type inference. Note that we don't have to
        ' specify the type for T when calling SlicesIndex - 
        ' the compiler infers it automatically.
        Console.WriteLine("index of zoo: " & SlicesIndex(s, "zoo"))

        ' … though we could also specify it explicitly.
        Dim _ = SlicesIndex(Of String)(s, "zoo")

        Dim lst As New List(Of Integer)()
        lst.Push(10)
        lst.Push(13)
        lst.Push(23)
        Console.WriteLine("list: " & String.Join(" ", lst.AllElements()))
    End Sub
End Module

This Visual Basic .NET code demonstrates the use of generics, which are similar to type parameters in Go. Here’s a breakdown of the translation:

  1. The SlicesIndex function is translated to a generic function in VB.NET. It uses the IComparable interface as a constraint, which is similar to the comparable constraint in Go.

  2. The List type is translated to a generic class in VB.NET. The internal structure uses a nested Element class to represent the linked list nodes.

  3. The Push method is implemented as a method on the generic List class.

  4. The AllElements method returns an array of elements instead of a slice, as VB.NET doesn’t have a direct equivalent to Go’s slices.

  5. In the Main subroutine, we demonstrate the use of these generic types and functions. Type inference is used when calling SlicesIndex, but we also show how to explicitly specify the type parameter.

To run this program, you would typically compile it using the VB.NET compiler and then execute the resulting assembly. The output would be similar to the Go version:

index of zoo: 2
list: 10 13 23

This example demonstrates how generics in Visual Basic .NET can be used to write flexible, reusable code that works with different types, similar to the functionality provided by generics in Go.