Ensure instance of class is initialized before using I'm beginning to work with VBA class modules more in Excel and want to make sure that no properties can be used if the class hasn't been initialized. Below is the class and my attempt to at doing so.

Private Type helper
    Prop1 As Boolean
    Prop2 As Boolean
    Prop3 As String
    Prop4 As String
End Type

Private m_initialized As Boolean

Private this As helper

Public Sub Init(ByVal Prop1 As Boolean, ByVal Prop2 As Boolean, ByVal Prop3 As String, ByVal Prop4 As String)
    this.Prop1 = Prop1
    this.Prop2 = Prop2
    this.Prop3 = Prop3
    this.Prop4 = Prop4

    m_initialized = True
End Sub

Public Property Get Prop1() As Boolean
    If Not m_initialized Then ThrowNotInitializedError

    Prop1 = this.Prop1
End Property

Public Property Get Prop2() As Boolean
    If Not m_initialized Then ThrowNotInitializedError

    Prop2 = this.Prop2
End Property

Public Property Get Prop3() As String
    If Not m_initialized Then ThrowNotInitializedError

    Prop3 = this.Prop3
End Property

Public Property Get Prop4() As String
    If Not m_initialized Then ThrowNotInitializedError

    Prop4 = this.Prop4
End Property

Public Function Self() As Foo
    Set Self = Me
End Function

Private Sub ThrowNotInitializedError()
    Err.Raise 5, "Init() not run.", "Values weren't initially assigned. Make sure they are assigned before use"
End Sub


The repetition of If Not m_initialized Then ThrowNotInitializedError is the part that I don't like. I can already imagine myself forgetting to put it on a property. Are there any other options?

Testing in a standard module to make sure it worked as I expected

Sub TestingFooInitializeProtection()
    Dim properlyInitialized As Foo
    Set properlyInitialized = New Foo
    properlyInitialized.Init True, False, "Input3", "Input4"
    Debug.Print properlyInitialized.Prop1
    Debug.Print properlyInitialized.Prop2
    Debug.Print properlyInitialized.Prop3
    Debug.Print properlyInitialized.Prop4

    Dim improperlyInitialized As Foo
    Set improperlyInitialized = New Foo
    'improperlyInitialized.Init False, True, "input3", "input4"
    Debug.Print improperlyInitialized.Prop1 'If above line is left commented out error is thrown.
    Debug.Print improperlyInitialized.Prop2
    Debug.Print improperlyInitialized.Prop3
    Debug.Print improperlyInitialized.Prop4
End Sub
A couple of quick points. 

If you are setting up a class, don't encapsulate a Type inside of it - you are only repeating what a class does! I am not sure where this anti-pattern comes from.

Within VBA do not raise errors unless absolutely necessary. Error raising and trapping will lead to unintended consequences and you can never be confident that they will be handled properly. Always handle the error explicitly. For starters, they can disrupt global variables.

You can create a Function in a module (let's call it NewFoo) with the correct signature - which creates the Foo instance and runs the Init method. This will make it a bit easier in the rest of your code to ensure you have the right sequence.

In Excel, you could make use of the xlError values to return an error if not initialised. This means that all your properties would be Variants (which has its own issues), something along the line of:

Public Property Get Prop1() As Variant
    Prop1 = IIF(m_initialised, CBool(Prop1_var), CVErr(xlErrNA))
End Property


Also, explicitly set m_initialised in the Class_Initialize routine to False. In theory not needed, but I prefer to be explicit.