0

I have the following code (sorry for the VB!) and I'm looking to avoid having to do a For Each loop to initialise the values from a String (ie "10,25,50") collection using Int32.TryParse.

Is there a way to do this? Like a Function(x) lambda kind of thing where it only adds items in the String collection when they pass an Int32.TryParse?

Dim options = ConfigHelper.GetContentValue("NavigationPaging", "PageSizeOptions").Split(CChar(","))
Dim optionsList As List(Of Integer) = New List(Of Integer)() 'Initialise the collection here to avoid the For Each
For Each item As String In options
    Dim i As Integer
    If Int32.TryParse(item, i) Then
        optionsList.Add(i)
    End If
Next

Thank you.

Robin French
  • 675
  • 6
  • 17

2 Answers2

1

I find your loop very readable. But if you want to use LINQ you could use this query:

Dim allIntegers = From opt In options
                  Let intOpt = opt.TryGetInt32()
                  Where intOpt.HasValue
                  Select intOpt.Value
Dim optionsList As List(Of Integer) = allIntegers.ToList()

I'm using this extension method which comes in handy for LINQ queries:

Module StringExtensions
    <Extension()>
    Public Function TryGetInt32(Str As String) As Nullable(Of Int32)
        If Str Is Nothing Then Return Nothing
        Dim num As Int32
        If Int32.TryParse(Str, num) Then Return num
        Return Nothing
    End Function
End Module

This method is much better than using a local variable as Int32.TryParse storage.

Community
  • 1
  • 1
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • I like this as a deeper solution adding the TryGetInt32 extension to String. The code is buried pretty deep so readability isn't an issue but we do have a restriction in our config systems that mean we have to do this kind of thing a lot and the extension method would help there. Thanks for the answer! I wasn't blocked on this or anything but just convinced there was a better way! – Robin French Mar 04 '16 at 13:48
1

The loop you have is clear and readable, but here is another way:

Dim options = {"10", "25", "50", "foo"}
Dim optionVals = Array.ConvertAll(Of String, Int32)(options, Function(c)
                                                                 Dim tmp As Int32 = 0
                                                                 Int32.TryParse(c, tmp)
                                                                 Return tmp
                                                             End Function).ToList()

Initialize tmp to whatever default value you want to use for bad values (-1, Int32.MinValue etc)

Another way would be to call a parser function:

optionVals = Array.ConvertAll(Of String, Int32)(options, Function(c) IntParser(c)).ToList()

Private Function IntParser(s As String) As Int32
    Dim n As Int32 

    If Int32.TryParse(s, n) Then
        Return n
    Else
        Return 0
    End If
End Function
Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178