Visual Basic .NET

Visual Studio (Windows) offers VB templates for console, Windows Forms, WPF, and class libraries.

34.1 Getting started

Visual Studio (Windows) offers VB templates for console, Windows Forms, WPF, and class libraries. VB.NET is case-insensitive, line-oriented, and statically typed; put Option Strict On at the top of files (or in the project) to forbid implicit narrowing conversions.

dotnet new console -lang VB -o HelloVB
cd HelloVB
dotnet run

34.2 Language essentials

Option Strict On
Imports System.Collections.Generic

Module Program
    Sub Main(args As String())
        Dim count As Integer = 3
        Dim price As Decimal = 19.99D
        Dim names As New List(Of String) From {"Ada", "Grace", "Linus"}
        names.Add("Margaret")

        For Each n In names
            Console.WriteLine($"{n,-10} {n.Length,3}")
        Next

        Dim ages As New Dictionary(Of String, Integer) From {{"Ada", 36}, {"Grace", 85}}
        If ages.ContainsKey("Ada") Then Console.WriteLine(ages("Ada"))

        Dim total = Enumerable.Range(1, 100).Sum()        ' type inferred as Integer
        Console.WriteLine($"Sum 1..100 = {total}, price x count = {price * count:C}")

        Try
            Dim x = Integer.Parse("abc")
        Catch ex As FormatException
            Console.WriteLine("Not a number: " & ex.Message)
        Finally
            Console.WriteLine("Done.")
        End Try
    End Sub
End Module

34.3 Classes, properties, inheritance, interfaces

Keywords: Inherits, Implements, Overridable/Overrides, MustInherit/MustOverride (abstract), NotInheritable (sealed), Shared (static), Me, MyBase, Protected, Friend (assembly-wide).

Public Interface IShape
    Function Area() As Double
End Interface

Public MustInherit Class Shape
    Implements IShape
    Public Property Name As String                       ' auto-implemented property
    Public MustOverride Function Area() As Double Implements IShape.Area
    Public Overrides Function ToString() As String
        Return $"{Name}: {Area():F2}"
    End Function
End Class

Public Class Circle
    Inherits Shape
    Public ReadOnly Property Radius As Double
    Public Sub New(r As Double)
        If r < 0 Then Throw New ArgumentOutOfRangeException(NameOf(r))
        Radius = r : Name = "Circle"
    End Sub
    Public Overrides Function Area() As Double
        Return Math.PI * Radius ^ 2
    End Function
End Class

Public Class Rect
    Inherits Shape
    Public Property W As Double
    Public Property H As Double
    Public Sub New(w As Double, h As Double)
        Me.W = w : Me.H = h : Name = "Rectangle"
    End Sub
    Public Overrides Function Area() As Double
        Return W * H
    End Function
End Class

34.4 Events

Public Class Thermostat
    Public Event TooHot(temperature As Double)
    Private _temp As Double
    Public Property Temperature As Double
        Get
            Return _temp
        End Get
        Set(value As Double)
            _temp = value
            If value > 30 Then RaiseEvent TooHot(value)
        End Set
    End Property
End Class

Module EventsDemo
    Private WithEvents sensor As New Thermostat()

    Private Sub OnTooHot(t As Double) Handles sensor.TooHot
        Console.WriteLine($"Warning: {t} degrees!")
    End Sub

    Sub Run()
        sensor.Temperature = 25
        sensor.Temperature = 33                   ' triggers the event
        AddHandler sensor.TooHot, Sub(t) Console.WriteLine("Second handler")
    End Sub
End Module

34.5 LINQ

Dim shapes As New List(Of Shape) From {New Circle(1), New Rect(2, 3), New Circle(2.5)}

' Query syntax
Dim bigOnes = From s In shapes
              Where s.Area() > 5
              Order By s.Area() Descending
              Select s.Name, Area = s.Area()

For Each item In bigOnes
    Console.WriteLine($"{item.Name} {item.Area:F1}")
Next

' Method syntax with lambdas
Dim totalArea = shapes.Sum(Function(s) s.Area())
Dim names = String.Join(", ", shapes.Select(Function(s) s.Name).Distinct())
Dim grouped = shapes.GroupBy(Function(s) s.Name)

34.6 Async / Await

Imports System.Net.Http

Module AsyncDemo
    Private ReadOnly client As New HttpClient()

    Async Function GetLengthAsync(url As String) As Task(Of Integer)
        Dim html As String = Await client.GetStringAsync(url)
        Return html.Length
    End Function

    Sub Main()
        Dim t = GetLengthAsync("https://example.com")
        Console.WriteLine("Downloading...")
        Console.WriteLine($"Length: {t.Result}")    ' in UI code, Await instead of blocking with .Result
    End Sub
End Module

34.7 Windows Forms

In Visual Studio you usually drag controls onto the form designer and double-click them to create event handlers — the same workflow Visual Basic 1.0 introduced in 1991. Windows Forms and WPF run on Windows; for cross-platform UI, consider Avalonia (C#-centric) or web front ends.

Imports System.Windows.Forms

Public Class MainForm
    Inherits Form
    Private ReadOnly txtName As New TextBox() With {.Left = 20, .Top = 20, .Width = 200}
    Private WithEvents btnGreet As New Button() With {.Text = "Greet", .Left = 230, .Top = 18}
    Private ReadOnly lblOut As New Label() With {.Left = 20, .Top = 60, .Width = 300}

    Public Sub New()
        Text = "Hello WinForms"
        Width = 360 : Height = 150
        Controls.AddRange({txtName, btnGreet, lblOut})
    End Sub

    Private Sub btnGreet_Click(sender As Object, e As EventArgs) Handles btnGreet.Click
        lblOut.Text = If(txtName.Text = "", "Please type a name.", $"Hello, {txtName.Text}!")
    End Sub
End Class