2

The following example is simplified. In my project I have a big List(of String) where I have to do some manipulations on the strings. For this I created a Sub where I do the manipulation and that should rewrite the Elements of the List(of String).

Module Module1
    Sub Main()
        Dim myList As List(Of String) = New List(Of String)
        myList.Add("1Tom")
        myList.Add("2Lisa")
        'Now I want apply a function to the List. As an example I created one that removes the first Letteer
        RemoveFirstChar(myList)
        For Each str As String In myList
            Console.Write(str)
        Next
        Console.Read()
    End Sub

    Sub RemoveFirstChar(ByRef myList As List(Of String))
        For Each str As String In myList
            str = str.Substring(2)
        Next
    End Sub
End Module

The string manipulation itself within the Sub works but it is not written into the initial List-Object. I actually thought that using ByRef would do this. Is it possible to do it this way and I just have a mistake or do I have to create a new List(of String) using a function and override the inital object. Like:

myList = foo(myList)

If both would work, what is more efficient? Since I have to do this on a List(of Strings) wiht few hundret thousand elements.

ruedi
  • 5,365
  • 15
  • 52
  • 88
  • 1
    `ByRef` would let you replace the list passed into `myList` with a completely different list, but you don't need it if you just want to modify the existing list. Because `List (Of T)` is a reference type, arguments are always mutable, `ByVal` or `ByRef` indicates the possibility to change the object referred to a different object, not the possibility to make changes to the state of the object. – Craig Dec 13 '18 at 14:57

2 Answers2

2

You have to use a For-loop, you can't modify the string with a For Each:

Sub RemoveFirstChar(ByRef myList As List(Of String))
    For i As Integer = 0 To myList.Count - 1
        Dim str As String = myList(i)
        myList(i) = str.Substring(2)
    Next
End Sub

You could modify the For Each object, but since strings are immutable you can't modify them but you need to replace them. You can't replace the whole object in a For Each, hence you need For.

But note that this will remove the first two chars(indexes are zero based in .NET) and also doesn't check if the string-length is >= 2. So this seems to be what you need:

myList(i) = If(str.Length >= 1, str.Substring(1), str)
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
2

In this code:

For Each str As String In myList
    str = str.Substring(2)
Next

you are assigning the result of your manipulation to str and str is just a local variable. You have to actually put the result into the List, which you do by setting the Item property. Get rid of that ByRef as it's a red herring. Just use a For loop like this:

For I = 0 To myList.Count - 1
    myList(i) = myList(i).Substring(2)
Next
jmcilhinney
  • 50,448
  • 5
  • 26
  • 46