【问题标题】:In a VB.Net procedure declaration, specify an object parameter of multiple possible types?在 VB.Net 过程声明中,指定多个可能类型的对象参数?
【发布时间】:2016-04-05 18:52:16
【问题描述】:

在 VB.Net 中声明一个过程时,其中传递的参数是一个对象,是否可以在“或”类型的语法中指定几种可能的对象类型?

例如,我想传递“列表”控件之一,以便该过程可以访问 .Items 集合。但是如果我尝试将参数概括并指定为 Windows.Forms.Control,则会生成错误,因为 .Items 不是 .Control 对象的成员。

我在 VB 语言参考中看到提到“类型列表”,这似乎几乎是我想要的,但不完全是。

这里有一些代码来演示这个问题...

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'.

一般意义上,我需要这样的语法...

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

但就实际工作代码而言,这是我所得到的......

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'.

这个可以吗?

【问题讨论】:

  • 只有Items 是您需要的吗?
  • 可以选择解决你的问题吗?

标签: vb.net visual-studio visual-studio-2012


【解决方案1】:

您可以检查TargetControl 是什么类型的控件,然后强制转换为该控件,访问它的属性。

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

另一种解决方案是重载方法。

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

阅读全文: Procedure Overloading - MSDN

【讨论】:

    【解决方案2】:

    如果 Items 集合是您唯一需要的东西

    如果 Items 集合是您需要从这些控件中获取的唯一内容,并且您需要从中读取数据,则可以将列表传递给您的方法并使用它:

    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
    

    并将Items 传递为List(Of Object)

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

    您还可以使用List(Of String) 或您的项目所在的任何其他List(Of T)


    如果需要传递整个 ListBox/ComboBox 或者需要操作

    如果您需要将整个 ListBox/ComboBox 对象传递给一个方法,或者您需要传递项目集合进行操作,则使用多个重载。例如对于整个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
    

    这是用法:

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

    如果您需要,可以对ListBox.ObjectCollectionComboBox.ObjectCollection 执行相同的操作。

    【讨论】:

      【解决方案3】:

      @visualvincent,谢谢。你的答案最接近我的需要。我非常喜欢紧凑且多功能的代码,并且用最少的时间做最多的事情。有时我会花很多时间编写一点点代码。

      我无法让 DirectCast() 工作。相反,经过大量阅读,我发现另一个使用过的问题与我的密切相关。它描述了 CTypeDynamic() 函数的使用,这是我的最后一块拼图。这里显示... 'objType' is not defined... Actually, it is, so why is this happening?

      下面是我拼凑出来的,我已经测试过了,效果很好……

      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
      

      谢谢大家的帮助..!!

      【讨论】:

      • 好吧DirectCast 需要一个静态类型。所以在某种程度上你使用CTypeDynamic是对的,但缺点是不建议在转换为已知类型或控件时使用它,因为它有时可能是“危险的”(这是因为它使用了转换运算符) . DirectCast 的编译速度也更快。 但是在您的情况下,您没有太多选择,并且由于控件是 ListBox 或 ComboBox,并且您已通过使用 @987654325 确保了这一点 @,使用没问题。
      • 我明白了,谢谢。很长一段时间以来,我一直是 Excel VBA 用户和谦虚的开发人员,而且我最近才开始研究 .Net。我学得很快,但我还有很长的路要走。 =-)
      • 我曾经在 VB6 中工作,但那时我对编程还很陌生,所以很快就切换到了 .NET。我认为由于它的本地结构,它很容易学习。
      • 我很快就喜欢上 .Net 的一件事是点符号。例如,在几乎所有以前的 BASIC 版本中,您可能会有这样的内容:Upper(Mid(myvar,1,2) & "Hello" & Str(32 + 32))。但在 .Net 中,这一切都像这样从左向右移动:Myvar.Substr(1,2).Concat("Hello",ToStr(32+32)).ToUpper。这是一个完全虚构的例子,但你明白了。一些字符串操作代码可能很难阅读。
      猜你喜欢
      • 2014-12-01
      • 2021-09-03
      • 2023-03-20
      • 2015-05-12
      • 1970-01-01
      • 2013-10-12
      • 2011-10-09
      • 1970-01-01
      • 2015-05-17
      相关资源
      最近更新 更多