0

Here are my definitions:

Public Class RouteDetails
    Public strRoad As String
    Public strToLane As String
    Public strToDirection As String
End Class

Public Class Route
    Public lstRouteDetails As List(Of RouteDetails)
End Class

ByVal lstRouteList As List(Of Route) (part of a function definition)

Sorry I tried to put the definitions section into a code block but, for some reason, it's not working.

Here is a section of the code, from that function, that I'm having problems with:

            rlcRoute = New Route
            lstRouteList.Add(rlcRoute)
            rdcRouteStep.strRoad = sdrNextJunction.GetValue(3)
            rdcRouteStep.strToLane = sdrNextJunction.GetValue(2)
            rdcRouteStep.strToDirection = sdrNextJunction.GetValue(1)
            For intloop = 0 To lstRouteList.Count - 1
                lstRouteList(intloop).lstRouteDetails.Add(rdcRouteStep)
            Next

The line, within the for loop, fails with:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

System.Collections.Generic.List.this[int].get.lstRouteDetails was Nothing.

If I understand the error correctly then it's telling me that I haven't created an instance of lstRouteDetails for this instance of Route? If that's correct then I would appreciate some advice on how to achieve this? I've tried a few combinations. The structure I'm trying to have is as follows:

RouteList is a list of objects of type route

Each Route object contains several objects of type RouteDetails

Thanks

Brian M Stafford
  • 6,742
  • 2
  • 15
  • 23
  • 1
    Does this answer your question? [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Tom W Apr 18 '20 at 18:34

1 Answers1

0

You don't need a class for you list. You can just create one in your form. I added a custom constructor to your class so you can set all the properties of the class in one line as demonstrated in the BuildList Sub. I had to add back the default constructor (no parameters). With the default constructor the properties are set individually. I also added an override of the .ToString method so we could use it in the Form. (See the OPCode method)

The Class

Public Class RouteDetails

    Public strRoad As String
    Public strToLane As String
    Public strToDirection As String

    Public Sub New()

    End Sub

    Public Sub New(Road As String, ToLane As String, Direction As String)
        strRoad = Road
        strToLane = ToLane
        strToDirection = Direction
    End Sub

    Public Overrides Function ToString() As String
        Return $"Road is {strRoad}, Lane is {strToLane}, Direction is {strToDirection}"
    End Function

End Class

The Form

Private RouteList As New List(Of RouteDetails)

Private Sub BuildList_Click(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim Route As New RouteDetails()
    Route.strRoad = "Main Street"
    Route.strToLane = "Park Lane"
    Route.strToDirection = "North East"
    RouteList.Add(Route)
    'or with the custom constructor
    Dim Route2 As New RouteDetails("Wall Steet", "Mulberry Lane", "South West")
    RouteList.Add(Route2)
End Sub

You can refer to the items in the list anywhere in the form.

Private Sub OPCode()
    MessageBox.Show(RouteList(1).strToLane)
    For Each item As RouteDetails In RouteList
        ListBox1.Items.Add(item) 'The ListBox calls .ToString on the item for display
    Next
End Sub

EDIT

Expanded Code

Public Class Route
    Public RouteDetailsList As New List(Of RouteDetails)
    Public Name As String

    Public Sub New(RDL As List(Of RouteDetails), nme As String)
        RouteDetailsList = RDL
        Name = nme
    End Sub

    Public Sub New()

    End Sub

    Public Overrides Function ToString() As String
        Return Name
    End Function
End Class

To test the code In the Form_Load call BuildRouteList

Private RouteList As New List(Of Route)

Private Sub BuildRouteList()
    Dim Details = {New RouteDetails("MainStreet", "Park Lane", "North East"), New RouteDetails("Wall Steet", "Mulberry Lane", "South West")}
    'Uses the construtor List(Of T)(IEnumerable<T>)
    Dim R As New Route(New List(Of RouteDetails)(Details), "1")
    RouteList.Add(R)
    Dim Details2 = {New RouteDetails("Wall Street", "Strawberry Lane", "South West"), New RouteDetails("Pine Street", "Little Maid Lawnd", "North")}
    Dim R2 As New Route(New List(Of RouteDetails)(Details2), "2")
    RouteList.Add(R2)
End Sub

In a button click call OPCode1 (assumes a ListBox1 is present

Private Sub OPCode1()
    MessageBox.Show(RouteList(0).RouteDetailsList(1).strToLane) 'shows Mulberry Lane
    For Each item As Route In RouteList
        ListBox1.Items.Add(item)
        For Each route In item.RouteDetailsList
            ListBox1.Items.Add(route) 'The ListBox calls .ToString on the item for display
        Next
    Next
End Sub
Mary
  • 12,341
  • 3
  • 17
  • 26
  • Thank you for your help. I haven't used classes for years and you've reminded me of things such as custom constructors. However I think your code only has two levels routelist and routedetails? I need three - Routelist, route and routedetails. A routelist can have several route objects and each route can have several routedetail objects. I can get two levels to work but not three. – user983325 Apr 19 '20 at 18:17
  • Thank you for your help. – user983325 Apr 22 '20 at 17:08