VB.NET Iterating through objects of a structure
Solution 1
If this is just a one time thing you're probably going to have an easier time using a Dictionary instead, but you could do this with Reflection if you prefer to keep the structure.
This little code snippet will list out each structure member for you in a StringBuilder
.
Dim sbOutput As New System.Text.StringBuilder
Dim t As Type = GetType(xyz)
For Each p As System.Reflection.FieldInfo In t.GetFields()
sbOutput.AppendLine(p.Name)
Next
Solution 2
An old question, but I actually found myself needing this, too, and this was one of the top results Google came up for me, so I figured I'd contribute for anyone who comes by this way in the future.
In my case, I'm basically using the structure as a collection of strings that I can easily reference via StrucName.Value1
, etc (basically an Enum of strings, like asked about here), and not have to worry as much about spell checking (as you'd have to do with a dictionary, whether you were using the dict!foo
method as commented on above or not). 90% of my usage I just need one or two of the values at a time, but I have found a spot or two in my code where it'd be nicer/easier to loop through all of the member values and perform (essentially) the same set of actions with each of them vs listing each one out on its own line.
I found a good answer to this that doesn't use reflection on another site, where one of the commenters suggested either overriding the ToString
function, or using a function that returns an array of the values. Of course, technically, this still requires you writing out all the members of the structure again one more time, but if Reflection really is heavy on performance, then this may be better.
I ended up using the function to return an array method like below:
Public Structure StrucName
Public Const Value1 As String = "Value1"
Public Const Value2 As String = "Value2"
Public Const Value3 As String = "Value3"
'etc
Public Shared Function GetMemberValues() As String()
Return {Value1, Value2, Value3} 'etc
End Function
End Structure
Then you can use it in code like this:
Dim values As String() = StrucName.GetMemberValues()
For Each value As String In values
'do stuff
Next
If your structure is of multiple value types, then you can use an ArrayList
, instead.
Public Structure StrucName
Public Const Value1 As String = "Value1"
Public Const Value2 As Integer = 2
Public Const Value3 As Boolean = True
'etc
Public Shared Function GetMemberValues() As ArrayList
Return New ArrayList From {Value1, Value2, Value3} 'etc
End Function
End Structure
Dim values As ArrayList = StrucName.GetMemberValues()
For Each value As Object In values
'do stuff
Next
And with the ArrayList
method, if needed, you can get the type of the original value through value.GetType()
, or any other similar operator or methods (so, with my example above, putting MsgBox(value.GetType().ToString())
in our "do stuff" area will pop message boxes with "System.String", "System.Int32", and "System.Boolean").
And I imagine this could be adapted to a number of situations. For example, if you needed both the member names and values, you could return a Dictionary
:
Public Shared Function GetMemberValues() As Dictionary(Of String, Object)
Return New Dictionary(Of String, Object) From {{"Value1", Value1}, {"Value2", Value2}, {"Value3", Value3}} 'etc
End Function
Or, if you're using a new enough version of VB (VB 14 or later), you can use the NameOf
operator (MS Doc here):
Public Shared Function GetMemberValues() As Dictionary(Of String, Object)
Return New Dictionary(Of String, Object) From {{NameOf(Value1), Value1}, {NameOf(Value2), Value2}, {NameOf(Value3), Value3}} 'etc
End Function
Dim values As Dictionary(Of String, Object) = StrucName.GetMemberValues()
For Each kvp As KeyValuePair(Of String, Object) In values
'do stuff
Next
And kvp.value.GetType()
still holds up.
Comments
-
Theveloper almost 2 years
I have a structure "xyz" with 3 string objects in it. "foo" "bar" and "abc" I want to iterate through the structure and compare the names of the objects.
Structure xyz dim foo as string dim bar as string dim abc as string End Structure
Pseudo:
For each x as object in xyz if x.Name = "foo" then 'bang end if End each
Is this possible?
-
schlebe over 2 yearscan you "improve" your answer in adding reflection code to add VALUE of p.Name variable ? Thanks