0

I am using a structure similar to that below. I need to loop through the 'Persons' ArrayList and set every salary to 100, whilst leaving the LastNames intact.

Structure Person
    Dim LastName As String
    Dim salary As Integer
End Structure

public class Test
    public Shared Sub Main
        Dim Persons As New ArrayList
        Dim Person As New Person

        With Person
            .LastName = "Smith"
            .salary = 50
        End With
        Persons.Add(Person)

        With Person
            .LastName = "Jones"
            .salary = 20
        End With
        Persons.Add(Person)

        With Person
            .LastName = "Brown"
            .salary = 80
        End With
        Persons.Add(Person)

    End Sub
End class

I realise that a simple For Each loop won't work here. I could copy each 'Person' to a second temporary arraylist and then delete the entry in the original arraylist, but I can't figure out how to change the salary for each person and 'Add' it back again whilst keeping the 'LastName' values as they originally were.

djv
  • 15,168
  • 7
  • 48
  • 72
Tim Makins
  • 394
  • 4
  • 12
  • 1
    A class with proper Properties would be more appropriate than a Structure here; likewise, a typed collection like a `List(Of T)` in place of the untyped ArrayList. Then loop – Ňɏssa Pøngjǣrdenlarp Apr 17 '17 at 17:56
  • What @Plutonix said. ArrayList belongs to the days that C# didn't have generics. It's deprecated in favor of List. You shouldn't use ArrayList in new code that targets .NET >= 2.0 unless you have to interface with an old API that uses it. From http://stackoverflow.com/a/2309699/832052 – djv Apr 17 '17 at 20:46
  • 1
    [Choosing Between Class and Struct](https://msdn.microsoft.com/en-us/library/ms229017(v=vs.110).aspx) – Ňɏssa Pøngjǣrdenlarp Apr 17 '17 at 21:02
  • 1
    @Plutonix `It will not have to be boxed frequently`, another argument against `ArrayList` too – djv Apr 17 '17 at 21:09

3 Answers3

2

Use a List(Of Person) instead of ArrayList (implicitly Of Object).

And just write a helper function to simplify adding. You can iterate over the List(Of Person) easily since now it's typed as Person

Structure Person
    Dim LastName As String
    Dim salary As Integer
End Structure

Sub Main()
    Dim Persons As New List(Of Person)()
    AddPerson(Persons, "Smith", 50)
    AddPerson(Persons, "Jones", 20) ' poor Jonesy
    AddPerson(Persons, "Brown", 80)
    For Each person In Persons
        person.salary = 100
    Next

End Sub

Public Sub AddPerson(persons As List(Of Person), lastName As String, salary As Integer)
    persons.Add(New Person() With {.LastName = lastName, .salary = salary})
End Sub

Another point

Your original code works with a For Each loop

For Each p As Person In Persons
    p.salary = 100
Next

but the risk of using an ArrayList is that you can add any object to it without error. Then you may run into an issue when casting the items back to Person if you weren't disciplined to always only add a Person to it. For example

Persons.Add(New Object)

For Each p As Person In Persons
    p.salary = 100
Next

would iterate until the loop encoutered the New Object at the end, then would result in a runtime error. A List(Of Person) would prevent it from ever being added in the first place, which is why it is always preferred over ArrayList for new development.

djv
  • 15,168
  • 7
  • 48
  • 72
1

A class might work better in this situation. Also, you could set the default value of Salary to be 100 so that each object already has a default value (no need to assign it later in a loop).

Public Class Person
  Dim LastName As String = ""
  Dim salary As Integer = 100

  Public Sub New()
      '
  End Sub

  Public Sub New(ByVal Last_Name As String, ByVal Salary As Integer)
      Me.LastName = Last_Name
      Me.salary = Salary
  End Sub
End Class
Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
ThePeter
  • 883
  • 1
  • 7
  • 15
0

The suggested loop:

For Each p As Person In Persons
    p.salary = 100
Next

did not work as it did not permanently write the new value to 'Persons', but after further searching I found a loop that does:

    For x = 0 To Persons.Count - 1
        Dim p As Person = Persons(x)
        p.salary = 100
        Persons(x) = p
    Next

I hope this helps someone else. I have also implemented the LIST ideas - thanks.

Tim Makins
  • 394
  • 4
  • 12