Solved

Passing unknown variabels

Posted on 2011-09-14
9
169 Views
Last Modified: 2012-05-12
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?
0
Comment
Question by:daghoff
9 Comments
 
LVL 5

Expert Comment

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

-MJC
0
 
LVL 40

Expert Comment

by:Jacques Bourgeois (James Burger)
Comment Utility
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




0
 
LVL 17

Expert Comment

by:nepaluz
Comment Utility
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

0
 

Author Comment

by:daghoff
Comment Utility
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?
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 40

Expert Comment

by:Jacques Bourgeois (James Burger)
Comment Utility
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


0
 

Author Comment

by:daghoff
Comment Utility
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?
0
 
LVL 40

Expert Comment

by:Jacques Bourgeois (James Burger)
Comment Utility
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.
0
 

Author Comment

by:daghoff
Comment Utility
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
0
 
LVL 40

Accepted Solution

by:
Jacques Bourgeois (James Burger) earned 500 total points
Comment Utility
First of all, .NET arrays always start at an indice of 0 in .Net. An array declared IA(3) has 4 elements, from IA(0) to IA(3). The indice you give in the declaration is not the number of elements, it is the indice of the upper bound. You ar losing resources by not using element 0.

Second, you do not need to pass the number of values as a parameter, you can get it from the array itself by calling array.GetLength(0). More often, you will however array.GetUpperBound(0) that gives you the indice of the highest element. The 0 is there to specify that you want the first dimension, because an array could be a multi-dimensioned array.

Third, I do not understand the cause of the error, one of those strange ones, probably due to the way For Each is implemented. But you can use a standard loop with a counter instead.

Fourth. Even then, the way you were doing the stuff, it would not have worked W(1), W(2) and W(3) are all of type Array. TypeOf would have not worked the way you implemented it. You need to look into the array to get the type of one of its elements. A being passed as an Object, simply cast each of its elements to an array (b in my code) and then look into the array.

Finally, this is one of those situations were Option Strict should be Off. If you work with Option Strict On, as you should, the following code won't work. Simply copy it in a module and set Option Strict Off in that module.
Option Strict Off
Public Module ModuleStrictOff
Private Sub Foo1(ByVal NumValues As Byte, ByVal ParamArray A() As Object)

  Dim Vc As Integer
  Dim b As Array

  For Vc = 0 To A.GetUpperBound(0)
    b = DirectCast(A(Vc), Array)
    Select Case True
      Case TypeOf b(1) Is Integer
        MsgBox("We have an Integer array")
      Case TypeOf b(1) Is String
        MsgBox("We have a String array")
        b(2) = "4444444444444"
      Case TypeOf b(1) Is Boolean
        MsgBox("We have a Boolean array")
    End Select
  Next

End Sub

Open in new window

0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Since .Net 2.0, Visual Basic has made it easy to create a splash screen and set it via the "Splash Screen" drop down in the Project Properties.  A splash screen set in this manner is automatically created, displayed and closed by the framework itsel…
Microsoft Reports are based on a report definition, which is an XML file that describes data and layout for the report, with a different extension. You can create a client-side report definition language (*.rdlc) file with Visual Studio, and build g…
This video discusses moving either the default database or any database to a new volume.
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now