Skip to content
AgileLogics
5 min read

Constructors and Shared Members

Prerequisites: Properties

Constructors

A constructor is a Sub New that runs when an object is created, making sure it starts in a valid state:

Public Class Product
    Public ReadOnly Property Name As String
    Public Property Price As Decimal

    Public Sub New(name As String, price As Decimal)
        If String.IsNullOrWhiteSpace(name) Then Throw New ArgumentException("Name is required.")
        Me.Name = name
        Me.Price = price
    End Sub

    Public Sub New(name As String)
        Me.New(name, 0D)
    End Sub

    Public Overrides Function ToString() As String
        Return $"{Name} ({Price:F2})"
    End Function
End Class

Module Program
    Sub Main()
        Dim tea As New Product("Tea", 3.5D)
        Dim sample As New Product("Sample")
        Console.WriteLine(tea)
        Console.WriteLine(sample)
    End Sub
End Module
Tea (3.50)
Sample (0.00)
  • Several constructors (overloads) can exist; Me.New(...) calls another one to avoid repeating code.
  • Once you write any constructor, the automatic parameterless one disappears — New Product() no longer compiles.
  • Overriding ToString controls how an object prints.

Shared members

A Shared member belongs to the class itself, not to any one object (C# calls this static):

Public Class Ticket
    Private Shared nextNumber As Integer = 1
    Public Shared ReadOnly Property Issued As Integer
        Get
            Return nextNumber - 1
        End Get
    End Property

    Public ReadOnly Property Number As Integer

    Public Sub New()
        Number = nextNumber
        nextNumber += 1
    End Sub

    Public Shared Function Describe(t As Ticket) As String
        Return $"Ticket #{t.Number:D3}"
    End Function
End Class

Module Program
    Sub Main()
        Dim a As New Ticket()
        Dim b As New Ticket()
        Console.WriteLine(Ticket.Describe(a))
        Console.WriteLine(Ticket.Describe(b))
        Console.WriteLine($"Issued: {Ticket.Issued}")
    End Sub
End Module
Ticket #001
Ticket #002
Issued: 2

Call shared members through the class name (Ticket.Describe). The shared field nextNumber is one value for the whole program, so every ticket gets a unique number.

Modules are shared classes

A Module is really a class whose members are all shared and which can't be instantiated. Use modules for helper functions and the program's entry point; use classes for things you create many of.

Factory methods

A Shared function that returns a new object can validate input and give the constructor a more descriptive name:

Public Class Temperature
    Public ReadOnly Property Celsius As Double

    Private Sub New(celsius As Double)
        Me.Celsius = celsius
    End Sub

    Public Shared Function FromCelsius(c As Double) As Temperature
        Return New Temperature(c)
    End Function

    Public Shared Function FromFahrenheit(f As Double) As Temperature
        Return New Temperature((f - 32) * 5 / 9)
    End Function
End Class

Module Program
    Sub Main()
        Console.WriteLine(Temperature.FromFahrenheit(212).Celsius)
        Console.WriteLine(Temperature.FromCelsius(21.5).Celsius)
    End Sub
End Module
100
21.5

The Private Sub New forces callers to use the factory methods.