1

When declaring a procedure in VB.Net, where a passed parameter is an object, is it possible to specify several possible object types in an "Or" type of syntax?

For instance, I want to pass one of the "list" controls so the procedure can access the .Items collection. But if I attempt to generalize and specify the parameter as Windows.Forms.Control, an error is generated because .Items is not a member of the .Control object.

I see mention of the "Type List" in the VB language reference, and this seems to almost be what I want, but not quite.

Here are some bits of code to demonstrate the issue...

Friend Sub ListFill( _
    ByRef SourceControl As Windows.Forms.WebBrowser, _
    ByRef TargetControl As Windows.Forms.Control)

    TargetControl.Items.Add(SourceControl.DocumentTitle)
    ' Error: 'Items' is not a member of 'System.Windows.Forms.Control'.

In a general sense, I need syntax like this...

Friend Sub name ( ByRef varname As { type1 Or type2 Or ... } = defaultvalue )

But in terms of actual working code, this is as far as I got...

Friend Sub ListFill( _
    ByRef SourceControl As Windows.Forms.WebBrowser, _
    Optional ByRef TargetControl As Windows.Forms.ListBox = Nothing, _
    Optional ByRef TargetControl As Windows.Forms.ComboBox = Nothing)

    'Error: Parameter already declared with name 'TargetControl'.

Can this be done?

DavidG
  • 113,891
  • 12
  • 217
  • 223
spinjector
  • 3,121
  • 3
  • 26
  • 56

3 Answers3

2

You could check what type of control TargetControl is and then cast to that control, accessing it's properties.

Friend Sub ListFill( _
ByRef SourceControl As Windows.Forms.WebBrowser, _
ByRef TargetControl As Windows.Forms.Control)
    If TargetControl.GetType() Is GetType(ListBox) Then
        DirectCast(TargetControl, ListBox).Items.Add(SourceControl.DocumentTitle)

    ElseIf TargetControl.GetType() Is GetType(ComboBox) Then
        DirectCast(TargetControl, ComboBox).Items.Add(SourceControl.DocumentTitle)

    End If
End Sub

Another solution is to overload the method.

Friend Sub ListFill( _
ByRef SourceControl As Windows.Forms.WebBrowser, _
ByRef TargetControl As Windows.Forms.ListBox)
    TargetControl.Items.Add(SourceControl.DocumentTitle)
End Sub

Friend Sub ListFill( _
ByRef SourceControl As Windows.Forms.WebBrowser, _
ByRef TargetControl As Windows.Forms.ComboBox)
    TargetControl.Items.Add(SourceControl.DocumentTitle)
End Sub

Read more: Procedure Overloading - MSDN

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
1

If Items collection is the only thing that you need

If Items collection is the only thing that you need from those controls and you need to read data from it, you can pass a list to your method and use it:

Public Sub DoSome(list As List(Of Object))
    'Use list here, for example:
    For Each item In list
        MessageBox.Show(item.ToString())
    Next
End Sub

And to pass Items as List(Of Object):

Dim list = Me.ListBox1.Items.Cast(Of Object)().ToList()
DoSome(list)

You can also use List(Of String) or any other List(Of T) that your items are.


If you need to pass whole ListBox/ComboBox Or you need manipulation

If you need to pass the whole ListBox/ComboBox object to a method, or you need to pass items collection for manipulation, then use multiple overloads. For example for whole ListBox/ComboBox:

Public Sub DoSome(list As ListBox)
    'Use list here, it's of type ListBox, for example
    MessageBox.Show(list.Name)
End Sub

Public Sub DoSome(combo As ComboBox)
    'Use combo here, it's of type ComboBox, for example
    MessageBox.Show(combo.Name)
End Sub

And here is the usage:

DoSome(Me.ComboBox1)
DoSome(Me.ListBox1)

The same could be done for ListBox.ObjectCollection or ComboBox.ObjectCollection if you need.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
0

@visualvincent, thank you. Your answer was closest to what I needed. I'm very much a devotee of compact & versatile code and doing the most with the least. Sometimes I spend a lot of time writing a tiny bit of code.

I was not able to make DirectCast() work. Instead, after much reading, I discover another used asked a question closely related to mine. It describe the use of the CTypeDynamic() function, and that was the last piece of my puzzle. Shown here... 'objType' is not defined... Actually, it is, so why is this happening?

Below is what I cobbled together, I've tested it and it works perfectly...

Friend Sub ListboxFill(ByRef SourceControl As Windows.Forms.WebBrowser, _
                       ByRef TargetControl As Windows.Forms.Control)

    Dim typ As System.Type = TargetControl.GetType
    Select Case typ
        Case GetType(ListBox), GetType(ComboBox)
            CTypeDynamic(TargetControl, typ).Items.Add(SourceControl.DocumentTitle)
    End Select

End Sub

Thank you all for your help..!!

Community
  • 1
  • 1
spinjector
  • 3,121
  • 3
  • 26
  • 56
  • Well `DirectCast` needs a static type. So in some way you're right to use `CTypeDynamic`, but the downside is that it's not recommended to use when casting to known types or controls, as it sometimes can be "dangerous" (this is because of it using conversion operators). DirectCast also compiles faster. **However** in your case you don't have much of a choice, and since the controls are either a ListBox or a ComboBox, _and you've ensured that_ by using `Select Case`, there's no problem with using it. – Visual Vincent Jan 03 '16 at 11:51
  • I see, thank you. I've been an Excel VBA user & modest developer for quite some time, and I'm only recently digging in to .Net. I'm learning fast, but I still have a long way to go. =-) – spinjector Jan 03 '16 at 19:07
  • I used to work in VB6, but it was when I still was rather new to programming so it didn't take me long to switch to .NET. I think it's easy to learn thanks to it's locigal structure. – Visual Vincent Jan 03 '16 at 19:09
  • One of the things I came to love very quickly about .Net is the dot-notation. For instance, in pretty much all versions of BASIC that came before, you might have something like this: Upper(Mid(myvar,1,2) & "Hello" & Str(32 + 32)). But in .Net it all moves from left to right like this: Myvar.Substr(1,2).Concat("Hello",ToStr(32+32)).ToUpper. This is a totally fictional example, but you get the idea. Some lines of string manipulation code can get really hard to read. – spinjector Jan 04 '16 at 08:42