views:

161

answers:

5

Is there a more elegant way to structure the following code, which takes a comma delimited string containing certain values in specific positions and assigns the values to the properties of an object?

        // split comma delimited items into a string array
        Dim items As String() = myList.Split(CChar(","))

        // Assign my Person object's properties

        // Name
        If items.Length > 0 Then
            Person.FullName = items(ItemIndex.FullName)
        End If

        // Address1
        If items.Length > 1 Then
            Person.Address1 = items(ItemIndex.Address1)
        End If

        // Address2
        If payload.Length > 2 Then
            Person.Address2 = items(ItemIndex.Address2)
        End If

EDIT: I'm open to C# examples, too.

A: 

My first instinct is to question why the input is in the form of a comma-delimited string. Assuming that you don't control the input and just have to live with it, I don't have a huge problem with this implementation. While I'm not intimately familiar with VB.net, I think there is a StringTokenizer. I would take a look at that and consider using that instead.

shsteimer
A: 

Looks fine. Are you expecting variable length arrays? You could:

If items.Length >= 3 Then
  // Assign properties
Else
  Throw New NotSupportedException("The line needs to have three items");
End If
steamer25
+4  A: 

You could use an enumerator but it's pretty much the same code just shorter.

Dim items = myList.Split(",").GetEnumerator
If items.MoveNext Then FirstName = items.Current
If items.MoveNext Then Address1 = items.Current
If items.MoveNext Then Address2 = items.Current

It's pretty tough to validate coming from a comma delimited string.

Of course if you are using objects you could pass something to your object and let your object parse it. I'm assuming you are able to use Linq in the next example.

Public Class Person
    Private Enum Position
        FirstName = 0
        Address1 = 1
        Address2 = 2
        LastName = 3
    End Enum
    Sub FillFromArray(ByVal Values() As String)
        FirstName = If(Values.ElementAtOrDefault(Position.FirstName), String.Empty)
        Address1 = If(Values.ElementAtOrDefault(Position.Address1), String.Empty)
        Address2 = If(Values.ElementAtOrDefault(Position.Address2), String.Empty)
        LastName = If(Values.ElementAtOrDefault(Position.LastName), String.Empty)
    End Sub
    Public FirstName As String
    Public Address1 As String
    Public Address2 As String
    Public LastName As String
End Class


Module MainModule
    Sub Main()
        Dim testString As String = "FirstName,Address 1,Address 2"
        Dim testPerson As New Person

        testPerson.FillFromArray(testString.Split(","))

        Debug.Assert(testPerson.FirstName = "FirstName")
        Debug.Assert(testPerson.Address1 = "Address 1")
        Debug.Assert(testPerson.Address2 = "Address 2")
        Debug.Assert(testPerson.LastName = String.Empty)

    End Sub
End Module
devSolo
+2  A: 

You could append a bunch of commas onto myList, and then you can skip the if statements:

// split comma delimited items into a string array
myList = myList & ",,," // One comma for every property.
Dim items As String() = myList.Split(CChar(","))

// Assign my Person object's properties
Person.FullName = items(ItemIndex.FullName)
Person.Address1 = items(ItemIndex.Address1)
Person.Address2 = items(ItemIndex.Address2)
Eclipse
+1 This is a bit of a hack, but I think it's the cleanest way to do it. Avoid all the conditionality by ensuring there are enough elements in the array.
Carl Manaster
It's kind of hacky, but removing corner-cases by adding extra data is a pretty common technique. Another example is when you have a matrix and you need to apply a transformation to each cell based on its neighbours. Instead of writing extra code to handle the sides and corners, just surround the matrix with the identity value for the function and only iterate over the interior cells.
Eclipse
A: 

If you wanted to rely on ItemIndex names matching the property names (convention) then you could use reflection to make it completely declarative. I can elaborate if you think that's a route you're interested in...

JohnOpincar