Link to home
Start Free TrialLog in
Avatar of daghoff
daghoff

asked on

Passing unknown variabels

How do you in VB.NET pass variabels to a subrutine if you dont know the variabel types or the number of variabels beeing passed to the sub before runtime?

In the sub there must also be a way to determin what info has been passed to the sub.

The sub will of cause have logic to process the values after it has been detected what type of data has been passed, but that is not part of this problem/solution.

is there a way to code this?
Avatar of Rainverse
Rainverse

If they're not complex variable types, can you just put them in an array, and pass that?

-MJC
For the Unknonw number of variables, you use a ParamArray.

For the unknow type, you define it as an array of Objects. My Visual Studio is being patched right now. I cannot check if I have it exactly right, but you get the concept.
Sub Foo(ByVal X As Byte, ByVal ParamArray A() As Object)

   Dim W As Object
   For Each W In A
      Select Case True
         Case TypeOf W Is Integer
             CInt(W) = 10
         Case TypeOf W Is TextBox
             DirectCast(W,TextBox).Text
         Case Else
             Throw New NotSupportedException ("Type not supported")
      End Select
   Next

End Sub

Open in new window




put these in a Dictionary(Of String, Object) from the calling procedure (which I assume knows the variabe types) and name them appropriately, e.g
1.Calling routine would:
Dim ObjDICT As New Dictionary(Of String, Object)
ObjDICT.Add("Label", New Label With {.Name = "MyLabel", .Text = "MyLabelText"})
ObjDICT.Add("TextBox", New TextBox With {.Name = "MyTextBox", .Text = "MyTextBoxText"})

Open in new window

2. The recieving routine will then use the keys of the dictionary to cast the object to its type
Function RecVFUNCT(ByVal xDict As Dictionary(Of String, Object) As Boolean
  For Each x In xDict.Keys
     Select Case x
        Case "Label"
           Dim Lbl = DirectCast(xDict.Item(x), Label)
        Case "TextBox"
           Dim Tbx = DirectCast(xDict.Item(x), TextBox)
     End Select
  Next
End Function

Open in new window

Avatar of daghoff

ASKER

Forgot to mention that the variabels to be passed are always two or more arrays of the same length.  The arrays may be defined as string, integer, boolean etc. but that is not known before the program is run.

You mean this can be solved by putting it all in a new array?
An array is an object. The array of Object variables used as a ParamArray can receive them. You will end up with an array of Array. The looping will just be a little more involved if you need to access individual values, something like:

Extra comment: ParamArray can be used alone. But if you have other parameters to pass, ParamArray should be the last one.

Sub Foo(ByVal x As Byte, ByVal ParamArray a() As Object)

  For Each w() As Object In A
    For i As Integer = 0 To 10 - 1
      Select Case True
        Case TypeOf w(0) Is Integer
          Debug.WriteLine(CInt(w(i)))
        Case TypeOf w(0) Is TextBox
          DirectCast(w(i), TextBox).Text = "Foo"
        Case Else
          Throw New NotSupportedException("Type not supported")
      End Select
    Next
  Next

End Sub

Open in new window

You should be able to call it with code similar to the following:
Dim a() As Integer
Dim b() As TextBox

'Fill the arrays

foo(10)
foo(10, a)
foo(10, b)
foo(10, a, b)
foo(10, b, a)

Open in new window


Avatar of daghoff

ASKER

Thanx for the answers. I liked the ParamArray approche best because it reduces the calling code to just one line as it should be.

But I forgot to mention that the arrays passed to the sub is to be returned. What my sub does is to sort them so the big question is how do I get them back? ParamArray does not allow ByRef.

I have an application where I need to sort arrays acording to one of them. How many and what type varies from place to place in the code. So insted of having the sort logic eveywhere I was hoping it could be put into a sub.

Perhaps there is no simple solution? Does anyone have a good aproche that realy solves my problem in a simpler way than just putting the sort logic eveywhere?

Or is there a specialiced multi array sort function/command already in place in VB.NET that I can use?
An array is a class and is already a reference. These types of objects are always passes as a reference, no matter if you use ByVal or ByRef. Changing ParamArray is the same as changing the passed array.

This is a common misconception. ByVal and ByRef works only for value types, objects made from a structure or form the basic types.
Avatar of daghoff

ASKER

I knew that arrays are always passed in a "ByRef" way, but acording to what I have learned about ParamArray that is not the case. But it actually works as my slitly modified code below shows. The value that is modified in the sub is accessable after the sub has finished.

Public Class Form1
    Dim IA(3) As Integer
    Dim SA(3) As String
    Dim BA(3) As Boolean

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        IA(1) = 3 : IA(2) = 2 : IA(3) = 1
        SA(1) = "B" : SA(2) = "A" : SA(3) = "C"
        BA(1) = True : BA(2) = False : BA(3) = True
        MsgBox("Initial value before calling sub: " & SA(2))
        Foo1(3, SA, IA, BA)
        MsgBox("Updated value after calling sub: " & SA(2))
    End Sub

    Private Sub Foo1(ByVal NumValues As Byte, ByVal ParamArray A() As Object)
        Dim Vc As Integer
        For Each W() As Object In A    '<<---- Error in this line!! *****************************************
            For Vc = 1 To NumValues
                Select Case True
                    Case TypeOf W(Vc) Is Integer
                        MsgBox("We have an Integer array")
                    Case TypeOf W(Vc) Is String
                        MsgBox("We have a String array")
                        W(Vc) = "4444444444444"
                    Case TypeOf W(Vc) Is Boolean
                        MsgBox("We have a Boolean array")
                End Select
            Next
        Next
    End Sub
End Class

But there are still one more problem. In the line marked above I get these type of errors shown below when the passed array is not defined as String. How do I overcome that problem?
Unable to cast object of type 'System.Int32[]' to type 'System.Object[]'.
Unable to cast object of type 'System.Boolean[]' to type 'System.Object[]'.

Regards
ASKER CERTIFIED SOLUTION
Avatar of Jacques Bourgeois (James Burger)
Jacques Bourgeois (James Burger)
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial