views:

329

answers:

4

I am attempting to create a generic function that the students in my introductory VB .NET course can use to search a single dimension array of a structure.

My structure and array look like this:

 Private Structure Survey  
    Dim idInteger As Integer
    Dim membersInteger As Integer
    Dim incomeInteger As Integer
    Dim stateString As String
    Dim belowPovertyLevelBoolean As Boolean
End Structure

Private incomeSurvey(199) As Survey

My generic function header looks like:

Private Function FindSurveyItem(Of xType As Structure)
 (ByVal surveyIDInInt As Integer, ByVal surveyArrayIn() As xType) As Integer

??????

End Function

My call to the function looks like:

 If FindSurveyItem(Of Survey)(CInt(idTextBox.Text), incomeSurvey) <> -1 Then

My question is: Is there a way to reference the individual structure fields in the array from inside the function? I was trying to make it generic so that the student could simply pass their array into the function - their structure may be named differently than mine and the field names may be different.

I suspect there are other ways to deal with this situation, but I was trying to keep it to just a simple single-dimension array of a structure. I don't think it is possible to do what I want, but I wondered what others thought.

A: 

What you're looking for are predicates, if using ,net 3.5

dim arr() as structure
Array.Find(arr, function(item)(item.MyMember = MemberToMatch))

More combersome in earlier versions, see here for more info

The point being, that your function would look very like an implementation of Array.Find (if you didn't want to use the function provided), and the students would need to write their own predicate function.

Binary Worrier
That's not necessarily a bad thing: he mentioned he's teaching a class. Sometimes class examples will re-implement common structures to show how it might be done.
Joel Coehoorn
I didn't mean it to sound like it was a bad thing, Honest ! Captenters study how trees grow, builders study what Concrete is made from, "Function writers" study how functions are written :)
Binary Worrier
what are Captenters? people who make cap tents? ;-)
Nathan Koop
Sure, like yurts (stupid bloody fingers have no stupid spell checker mutter grumble grumble mutter . . . )
Binary Worrier
A: 

No, there isn't. You can't know the type at compile time, therefore you cannot access members of that type. You would need change from a structure to a class that must implement IComparable so that you can use CompareTo between the item you pass in and the array you are passing in.

Though it's not entirely clear what you are trying to do within your method so I'm guessing by the name of the method.

Garry Shutler
Garry, thanks. I knew that the actual type was unknown at compile time - that is what made me suspect that there was not a straightforward solution. I was just personally curious about a possible way to do it. You confirmed what I suspected.
+1  A: 

If you have a genric type parameter T you are only able to access members of instances of T that are known to exist at compile time. As every type derives from Object you have only the members of Object availiable - ToString(), GetType(), GetHashCode(), and Equals().

If you want to access other members you have to constrain what T is allowed to be. In your situation a interface would be the way to go. See MSDN for details.

You could also try to use reflection or check the actual type at runtime an perform a cast. The first is hard to impossible to do if you do not know much about the types you will get. And the later requires you to know possible types at compiletime and will not work in your situation, too.

Another way might be to pass a delegate to the search method that performs the actual comparison.

Daniel Brückner
A: 

You can use reflection to get those fields, but in this case that wouldn't have much meaning. How would you know that the passed type has the field you're looking for? There are other problems with that code as well.

Instead, to do this I would normally create an interface for something like this that had a public ID property, and constrain my input to the function to implement that interface, or as others mentioned use a built-in feature in the clr.

But that may be ahead of where your students are. If you just want an example of a generic function, my suggestion is to show them a type-safe implementation of the old vb imediate if function:

Public Function IIf(Of T)(ByVal Expression As Boolean, ByVal TruePart As T, ByVal FalsePart As T) AS T
    If Expression Then Return TruePart Else Return FalsePart
End Function

Note that this is obsolete, too, as in VS2008 and beyond you can use the new If operator instead, which will work better with type inference and won't try to evaluate the expression that isn't returned.

Joel Coehoorn