Maxwell175
Maxwell175

Reputation: 1923

How do I copy Array values to a structure

I would like to to copy that values of an array into a Structure.

Example:

' The Array
Dim Columns(2) As String

' The Structure
Private Structure Fields
    Public FName As String
    Public LName As String
    Public Email As String
End Structure

' I would like to map it like so:
Fields.FName = Columns(0)
Fields.LName = Columns(1)
Fields.Email = Columns(2)

Obviously I could write a function if it was so simple, but really there are over 25 columns and it's a pain to write a function that would map it.

Is there some way to do this?

Upvotes: 0

Views: 915

Answers (1)

jmcilhinney
jmcilhinney

Reputation: 54417

There really is no simple way that will work in all cases. What you are complaining is too much effort is the only way to guarantee that it will work in all cases.

That said, if you can guarantee that the number of elements in the array matches the number of properties/fields in the structure/class and that they are in the same order and of the same types then you could use Reflection in a loop, e.g.

Private Function Map(source As Object()) As SomeType
    Dim result As New SomeType
    Dim resultType = result.GetType()
    Dim fields = resultType.GetFields()

    For i = 0 To source.GetUpperBound(0)
        fields(i).SetValue(result, source(i))
    Next

    Return result
End Function

EDIT:

The code I have provided works as is if SomeType is a class but, as I missed the first time around, not for a structure. The reason is that structures are value types and therefore a copy of the original object is being sent to SetValue, so the field value never gets set on that original object. In theory, to prevent a copy being created, you should be able to simply box the value, i.e. wrap it in an Object reference:

Private Function Map(source As Object()) As SomeType
    Dim result As Object = New SomeType
    Dim resultType = result.GetType()
    Dim fields = resultType.GetFields()

    For i = 0 To source.GetUpperBound(0)
        fields(i).SetValue(result, source(i))
    Next

    Return DirectCast(result, SomeType)
End Function

As it turns out though, the VB compiler treats that a little differently than the C# compiler treats the equivalent C# code and it still doesn't work. That's because, in VB, the boxed value gets unboxed before being passed to the method, so a copy is still created. In order to make it work in VB, you need to use a ValueType reference instead of Object:

Private Function Map(source As Object()) As SomeType
    Dim result As ValueType = New SomeType
    Dim resultType = result.GetType()
    Dim fields = resultType.GetFields()

    For i = 0 To source.GetUpperBound(0)
        fields(i).SetValue(result, source(i))
    Next

    Return DirectCast(result, SomeType)
End Function

Upvotes: 1

Related Questions