简体   繁体   中英

vb.net Object Array Losing Values - Handling a collection of objects

I hope complete code is below.

Q1: Why do the 2 Debug writes produce different values?

The first Debug Write performs correctly but the second shows each object in the array has the same values as the last object created in the For Each loop.

Q2: Is there a better way to handle a collection of objects other than an array?

Test Values at the end.

Thanks for any help.

Code:

Public Class Form1

    Public facilities() As Facility


    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim FileToImport As String = GetFileName("Select Facility Import File")
        Dim facility As New Facility
        Dim counter As Integer = 0
        Dim words() As String
        Dim i As Integer

        'Sample line format: FacID<TAB>FacSingleChar<TAB>ParentFacID

        Try
            If File.Exists(FileToImport) Then

                For Each line As String In File.ReadLines(FileToImport)

                    words = line.Split(vbTab)

                    With facility
                        .FacilityID = words(0)
                        .FacilitySingleCharID = words(1)
                        .ParentFacilityID = words(2)
                    End With

                    ReDim Preserve facilities(counter)

                    facilities(counter) = facility

                    Debug.WriteLine("First Print: " & facilities(i).FacilityID & vbTab & facilities(i).ParentFacilityID & facilities(i).FacilitySingleCharID)

                    counter = counter + 1

                Next line


                For i = 1 To facilities.GetUpperBound(0)

                    Debug.WriteLine("Second Print: " & facilities(i).FacilityID & vbTab & facilities(i).ParentFacilityID & facilities(i).FacilitySingleCharID)

                Next

            End If

        Catch ex As Exception

            MsgBox(ex.Message & vbTab & ex.ToString)

        End Try


    End Sub

    Private Function GetFileName(ByVal DialogTitle As String, Optional ByVal FileFilter As String = "All Files (*.*)|*.*") As String

        Dim oDlg As New OpenFileDialog()
        Dim FileName As String = ""

        Try

            With oDlg
                .Title = DialogTitle
                .Filter = FileFilter
                .ShowDialog()
                FileName = .FileName
            End With

            Return FileName

        Catch ex As Exception

            Return ""

        End Try

    End Function
End Class

Public Class Facility


    Private m_FacilityID As String = Space(4)
    Private m_ParentFacilityID As String = Space(4)
    Private m_FacilitySingleCharID As String = Space(1)


    Public Property FacilityID As String
        Get
            Return m_FacilityID
        End Get
        Set(ByVal value As String)
            m_FacilityID = value.PadRight(4)

        End Set
    End Property

    Public Property ParentFacilityID As String
        Get
            Return m_ParentFacilityID
        End Get
        Set(ByVal value As String)
            m_ParentFacilityID = value.PadRight(4)
        End Set
    End Property

    Public Property FacilitySingleCharID As String
        Get
            Return m_FacilitySingleCharID
        End Get
        Set(ByVal value As String)
            If Len(value) = 1 Then
                m_FacilitySingleCharID = value
            Else
                m_FacilitySingleCharID = "?"
            End If
        End Set
    End Property


End Class

Test Data for Import File:

Import File should have 3 tab delimited columns:

(There should not be blank between entries, that was the only way to make them readable here)

APC A NCT

BAB B NCT

BABG C NCT

CCR D NCT

There are a couple of issues at work here.

The most straightforward one is that on your second print loop, your For..Next loop index variable i has 1 as the start value where it should be 0.

The second is a little more complicated.

You create a new facilities object and each pass through the loop, you assign new values to the object and assign the object to the newly created last element in the array.

The problem is to do with how objects work and how they are used

Each time through the loop, you just assign new values to the same object and store that object in every element of the array. However what the code is doing in the background is not storing a new object each time with all the new values, it's storing a reference to the same object in each element and changing the values on each pass through the loop. That's why all your values in the array are the same.

What you need to do is move the line

Dim facility As New Facility

into the loop so that a new object is created on each pass through the loop

Like this

For Each line As String In File.ReadLines(FileToImport)
    Dim facility As New Facility
    words = line.Split(vbTab.ToCharArray)
    With facility
       .FacilityID = words(0)
       .FacilitySingleCharID = words(1)
       .ParentFacilityID = words(2)
    End With
    ReDim Preserve facilities(counter)
    facilities(counter) = facility
    Debug.WriteLine("First Print: " & facilities(counter).FacilityID & vbTab & facilities(counter).ParentFacilityID & facilities(counter).FacilitySingleCharID)
    counter = counter + 1
Next line

Initially objects can be confusing, but have a look at reference types and value types and variable scope.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM