Search code examples
arraysvb.netobjectnullreferenceexception

How do I declare arry of objects outside a soubroutine in VB.net


I wrote a code to demonstrate the issue:

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        doSomething()
    End Sub

    Dim controlArr() As Object = {NumericUpDown1, NumericUpDown2, NumericUpDown3, NumericUpDown4, CheckBox1, CheckBox2, CheckBox3, CheckBox4}
    Private Sub doSomething()
        Dim testStr As String = ""
        For Each control In controlArr
            Select Case control.GetType
                Case GetType(NumericUpDown)
                    control.value = 1
                Case GetType(CheckBox)
                    control.checked = True
            End Select
        Next
    End Sub
End Class

When I run the code I receive Null Referenece Exception "Object reference not set to an instance of an object", the error disapears when I declare the controlArr array inside DoSomething subroutine. Anyway I would prefer having it declared outside since I am using it in many functions. I would like to understand it better so if you provided me with a topic I could read up on I would be very grateful. Thank you very much for your help.


Solution

  • The issue is that declarations are processed before the constructor. That means that this line:

    Dim controlArr() As Object = {NumericUpDown1, NumericUpDown2, NumericUpDown3, NumericUpDown4, CheckBox1, CheckBox2, CheckBox3, CheckBox4}
    

    is executed before the code that creates all the controls on the form and assigns them to those fields. As such, all the fields are Nothing at the time that code is executed and so your array contains a whole lotta nothin'. There's no issue creating objects to initialise fields like that and that code does successfully create an array. It's just that you are implicitly setting every element of that array to Nothing so that's what you get to use later on.

    If you want to reference any control then you have to wait until after the form's controls are created. That means, at the earliest, after the call to InitializeComponent in the constructor. More generally, you should do it in the Load event handler, e.g.

    Dim controlArr As Object()
    
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Form1.Load
        controlArr = {NumericUpDown1, NumericUpDown2, NumericUpDown3, NumericUpDown4, CheckBox1, CheckBox2, CheckBox3, CheckBox4}
    End Sub