Procedures: Subs and Functions
8.1 Sub vs Function
Sub Greet(name As String) ' no return value
Console.WriteLine($"Hello, {name}")
End Sub
Function Add(a As Integer, b As Integer) As Integer ' returns a value
Return a + b
End Function
Function Multiply(a As Integer, b As Integer) As Integer
Multiply = a * b ' legacy style: assign to the function name
End Function
Greet("Ana")
Dim sum = Add(2, 3)
Call Greet("Bo") ' Call keyword (optional, legacy)8.2 ByVal vs ByRef
With reference types (classes), ByVal passes a copy of the reference. The object itself can still be modified, but you can't replace the caller's reference.
Sub DoubleIt(ByRef value As Integer) ' modifies the caller's variable
value *= 2
End Sub
Sub TryChange(ByVal value As Integer) ' ByVal is the default: works on a copy
value = 100
End Sub
Dim x = 5
DoubleIt(x) ' x = 10
TryChange(x) ' x is still 108.3 Optional and Named Parameters
Sub CreateUser(name As String, Optional age As Integer = 18, Optional role As String = "User")
Console.WriteLine($"{name}, {age}, {role}")
End Sub
CreateUser("Ana")
CreateUser("Bo", 25)
CreateUser("Cy", role:="Admin") ' named argument skips optional ones
CreateUser(role:="Guest", name:="Dee") ' any order with names8.4 ParamArray (Variable Arguments)
Function Sum(ParamArray numbers() As Integer) As Integer
Dim total = 0
For Each n In numbers
total += n
Next
Return total
End Function
Console.WriteLine(Sum(1, 2, 3, 4))
Console.WriteLine(Sum()) ' empty array8.5 Overloading
Function Area(radius As Double) As Double
Return Math.PI * radius ^ 2
End Function
Function Area(width As Double, height As Double) As Double
Return width * height
End Function
' The Overloads keyword is optional within one class (required when overloading across inheritance)8.6 Recursion
Function Factorial(n As Integer) As Long
If n <= 1 Then Return 1
Return n * Factorial(n - 1)
End Function
Function Fibonacci(n As Integer) As Long
Return If(n < 2, n, Fibonacci(n - 1) + Fibonacci(n - 2))
End Function8.7 Returning Multiple Values
Note: VB supports tuple types and named elements, but not C#-style deconstruction into separate variables. Access the elements by name instead.
' 1. ByRef parameters
Sub MinMax(values() As Integer, ByRef min As Integer, ByRef max As Integer)
min = values.Min() : max = values.Max()
End Sub
' 2. Tuples (VB 15+)
Function GetStats(values() As Integer) As (Min As Integer, Max As Integer, Avg As Double)
Return (values.Min(), values.Max(), values.Average())
End Function
Dim stats = GetStats({3, 7, 1})
Console.WriteLine($"{stats.Min} {stats.Max} {stats.Avg}")8.8 Caller Information Attributes
Imports System.Runtime.CompilerServices
Sub Log(message As String,
<CallerMemberName> Optional member As String = "",
<CallerLineNumber> Optional line As Integer = 0)
Console.WriteLine($"[{member}:{line}] {message}")
End Sub