I have started a new job and I need to write in vb.net
For the code I am writing, I need to map from an integer to a panel. I would like this mapping to have scope for the entire file, not just a single subroutine, so I have tried declaring it as such:
Private ReadOnly MAP = New Dictionary(Of Integer, Panel) From {
{0, Nothing},
{1, Foo},
{2, Bar},
...
}
Then, I have a subroutine something like this (simplified)
Private Sub Thing(ID As Integer)
If MAP.Item(ID) IsNot Nothing
MAP.Item(ID).Visible = True
End If
End Sub
and let say I call Thing(1)
, that should make Foo
visible, but instead nothing happens. If I Dim MAP
inside of Thing
, it works as expected. I obviously don't want to be constructing my map everytime I call the sub though, as that kinda defeats the purpose of a map by adding the overhead of constructing it at every use (although it is more readable).
Basically what I'm wondering is why the construction of MAP
doesn't remain when I use it? Shouldn't all member variables be constructed before we begin executing any of the methods of a class, if declared in this way?
The trick is here is Forms are classes, which have a defined initialization order where fields (like MAP
) are initialized before the constructor runs. This makes sense. If you have a complex constructor, you would want and expect to be able to use defined field values there.
However, form controls are initialized in the InitializeComponent()
method called at the end of the constructor. Therefore, at the time the MAP
variable is initialized, the Foo
and Bar
member variables exist, but they are not yet initialized to refer to the actual control objects they are intended to represent.
To fix this, you need to change the code so items are added to the MAP
collection after the InitializeComponent()
method runs.