mysticgohan53
mysticgohan53

Reputation: 415

List of Struct that contains List not initializing correctly

I have the following properties:

Protected y As New RecordType
Protected x As New Record
Protected ListOfRecordTypes As New List(Of RecordType)

I have the following structs:

Public Structure Record
    Public RecordType As String
    Public Location As String
End Structure

and

Public Structure RecordType
    Public Focus As String
    Public Records As List(Of Record)
End Structure

I loop through and add a bunch of RecordType's to the ListofRecordTypes list with this function:

Private Sub GetFocus()

        Dim CompData As SqlDataReader


        Dim connStringOOC = CONNSTRING2
        Dim qry As String = "SELECT DISTINCT Focus FROM dbo.Table"

        Using conn As New SqlConnection(connStringOOC)
            Dim cmd As New SqlCommand(qry)
            cmd.Connection = conn
            conn.Open()
            CompData = cmd.ExecuteReader()
            Try
                Do While CompData.Read()
                    y.Focus = CompData("Focus")
                    ListOfRecordTypes.Add(y)
                Loop

            Catch ex As Exception
                Debug.WriteLine(ex.Message)
            End Try
        End Using
    End Sub

Once I have done that, I want to call this function:

Private Function GetRecordType(ByVal focus As String) As List(Of Record)
        Dim CompData As SqlDataReader
        Dim x As New Record
        Dim y As New List(Of Record)
        Dim connStringOOC = CONNSTRING

        Dim qry As String = "SELECT DISTINCT RecordType FROM dbo.Table WHERE Focus = @Focus"

        Using conn As New SqlConnection(connStringOOC)
            Dim cmd As New SqlCommand(qry)
            cmd.Connection = conn
            conn.Open()
            cmd.Parameters.AddWithValue("@Focus", focus)
            CompData = cmd.ExecuteReader()
            Try
                Do While CompData.Read()
                    x.RecordType = CompData("RecordType")
                    y.Add(x)
                Loop

            Catch ex As Exception
                Debug.WriteLine(ex.Message)
            End Try
        End Using
        Return y
    End Function  

This function is supposed to loop through the ListOfRecordTypes and return a list of Records that are associated with the Focus of the RecordType.

I want to print all the RecordTypes and their associated records, but when I loop through the recordtypes, the list has nothing in it.

I'm not sure if I'm completely doing it wrong, or if I missed something simple.

Any help would be greatly appreciated.

Thanks

Upvotes: 1

Views: 46

Answers (2)

David
David

Reputation: 218877

This scenario is likely going to cause problems...

Protected y As New RecordType

Private Sub GetFocus()
    ' other code

    Do While CompData.Read()
        y.Focus = CompData("Focus")
        ListOfRecordTypes.Add(y)
    Loop

    ' other code
End Sub

This is because you're re-using the same y instance every time. When adding items to a list in a loop like this, you'll want to create a new instance of the item with each iteration of the loop. Modifying and re-adding the same instance will likely have unexpected behaviors.

Instead, you probably want to structure it more like this:

Private Sub GetFocus()
    ' other code

    Do While CompData.Read()
        Dim y As New RecordType
        y.Focus = CompData("Focus")
        ListOfRecordTypes.Add(y)
    Loop

    ' other code
End Sub

There's no need to re-factor the y variable to a higher scope, semantically and structurally it's a lot more clear and safe to just create a new one in each loop like this.

Upvotes: 1

the_lotus
the_lotus

Reputation: 12748

I don't see all your code so I'm taking a guess here. Structure are not like class. When you pass them in a method, the method will have a copy not a reference.

Structure Test
    Public Value As String
End Structure

Sub Main()

    Dim a As New Test

    SetValues1(a)
    Console.WriteLine(a.Value) ' Empty

    SetValues2(a)
    Console.WriteLine(a.Value) ' prints 123

    Console.ReadLine()

End Sub

Sub SetValues1(ByVal b As Test)
    b.Value = "123"
End Sub

Sub SetValues2(ByRef b As Test)
    b.Value = "123"
End Sub

Here's an other example using a list. After I get the object from the list, I now have a copy of that object.

Structure Test
    Public Value As String
End Structure

Sub Main()

    Dim x As Test
    Dim l As New List(Of Test)

    l.Add(New Test)
    x = l(0)
    x.Value = "123"

    Console.WriteLine(l(0).Value) ' Empty
    Console.WriteLine(x.Value) ' prints 123
    Console.ReadLine()

End Sub

The easiest solution might be to use classes instead of structure.

Upvotes: 1

Related Questions