【问题标题】:What exactly are parentheses around an object reference doing in VB.NET?在 VB.NET 中,对象引用周围的括号究竟是做什么的?
【发布时间】:2023-03-19 01:31:01
【问题描述】:

我有一些程序将Control 对象引用作为参数。

在我的整个项目中,我有一堆 Controls,它们具有不同的派生类型,例如 ButtonTextBoxPictureBoxListBox 等。

我正在调用该过程并正常传递引用:

Procedure(controlRef)

我更改了项目配置中的一些警告通知。我猜它正在将隐式转换通知从“无”更改为“警告”,导致在调用这些程序的任何地方都会出现类似于以下内容的警告:

“在将 'ByRef' 参数 'parControl' 的值复制回匹配的参数时,从 'Control' 到 'Button' 的隐式转换。”

这是有道理的,我正在执行隐式转换,但请稍等,我将 Button 传递给 Control 参数,而不是像上面所说的那样将 Control 传递给 Button ,我有点困惑这里发生了什么。

无论如何,我看看“显示潜在修复”并没有修复建议,只有“抑制”或“配置”选项,好吧。因此,我使用DirectCast(controlRef, Control) 进行了显式转换,以查看是否会删除隐式转换的警告,它确实如此,但它再次被冗余转换警告取代,这是有道理的。因此,我使用潜在的修复程序删除了强制转换,并且过程调用中的参数在其周围留下了括号并且没有更多警告。

Procedure((controlRef))

这里到底发生了什么?

【问题讨论】:

  • Procedure的签名是什么?
  • Procedure(ByRef param As Control)。如果我删除 ByRef 我不会收到有关隐式转换的投诉,并且不需要围绕参数的括号。我只是想知道那些括号在做什么?

标签: vb.net casting


【解决方案1】:

由于Procedure 的签名是Sub Procedure(ByRef param As Control),并且您将Button 传递给该方法,因此编译器正确地警告您有关隐式转换。

想象一下这是Procedure的定义:

Sub Procedure(ByRef param As Control)
    param = New Label()
End Sub

如果你这样称呼它:

Dim button = New Button()
Procedure(button)

那么你实际上是在调用这段代码:

Dim button As Button = New Button()
button = New Label()

因此编译器警告。

如果您将签名更改为Sub Procedure(ByVal param As Control),则不可能将分配回调用变量,并且警告将消失。

使用额外的括号会强制调用ByVal 而不是ByRef。见https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/procedures/how-to-force-an-argument-to-be-passed-by-value

【讨论】:

  • 我只需要知道括号在做什么,但谢谢。
  • @typedefMiles_WilliamsMILO - 您的问题要求的不仅仅是括号。
  • 我的问题是“VB.NET 中对象引用周围的括号到底是做什么的?”这是标题。哈哈。但我很欣赏额外的信息。干杯。
  • @typedefMiles_WilliamsMILO - 你确实说过,“这是有道理的,我正在做一个隐式转换,但请稍等,我将 Button 传递给 Control 参数,不是 ControlButton 就像它说的那样,我有点困惑这里发生了什么。”所以当你问“这里到底发生了什么?”我认为这意味着问题中提出的所有问题。
【解决方案2】:

这不是问题的答案,但可能是实际问题的解决方案。它还需要大量代码,因此我认为答案是最佳选择。

人们不得不想知道为什么您首先声明了该参数ByRef。许多人在不需要时这样做,因为就像在 VB6 中一样,他们认为它会阻止对象被复制。情况并非如此,因为引用类型对象,即类实例,无论如何在按值传递时都不会被复制。这就是引用类型的全部意义,即变量的值是引用,而不是对象,因此按值传递只会复制引用,而不是对象。如果您没有在方法内为该参数分配任何内容,则应将其声明为ByVal

如果您要分配给方法内的参数,那么解决方案是将方法声明为泛型。这样一来,参数就不是Control,而是您传入的类型。最简单的形式是:

Private Sub Procedure(Of T)(ByRef control As T)
    '...
End Sub

但这可能还不够,因为这将允许您将任何对象作为参数传递。将方法限制为仅接受控件:

Private Sub Procedure(Of TControl As Control)(ByRef control As TControl)
    '...
End Sub

现在您只能将控件传递给方法,但在方法内部,参数将被视为您传递的参数的实际类型,例如如果你传递了Button,那么TControl 就固定为Button。如果您需要在方法内创建适当类型的控件,那么您还需要另一个限制,这使您能够假设无参数构造函数,例如

Private Sub Procedure(Of TControl As {New, Control})(ByRef control As TControl)
    control = New TControl With {.Location = New Point(100, 100),
                                 .Size = New Size(50, 25)}

    '...
End Sub

该代码意味着,在方法内部,您知道参数的类型是 Control 或派生自该类型,并且您可以通过调用无参数构造函数来创建新实例。

【讨论】:

  • 最初不是我的代码。维护旧应用程序。当我实际上遇到这个时,我正在经历并删除所有 ByRefs。就像我说的,当它被删除时没有问题。我只是想知道括号在做什么,因为我使用 VB.Net 和括号进行的搜索没有提供任何答案。是的,写这篇文章的人是一个 VB6 程序员。所以你说的很有道理。
  • 作为记录,我只是对 "vb.net argument in parentheses" 进行了 Bing 搜索,并且在接受的答案中链接到的页面是第三个结果。除非您阅读它,否则无法保证您会知道这就是您要寻找的东西,但我希望您会阅读第三个结果。就个人而言,我发现 Bing 比 Google 更适合 .NET 开发,而 Google 并没有返回相同的结果。它确实返回了this。它适用于 VB6,但两种语言的答案都是一样的。不确定您搜索的是什么。
  • 有趣。你是对的。谷歌没有做到这一点。我首先尝试查看 VB Language Reference 并没有看到任何东西,然后谷歌也没有看到任何东西。只是一堆关于 VBA 和调用函数的东西,并且需要在 VB.NET 中包含括号。下次我进行与微软相关的搜索时,我一定会记住 Bing。另外,我不知道这也与争论有关。我只是在寻找与对象、​​引用、括号、vb.net 之类的匹配项。当您知道要查找的内容时,查找内容会更容易;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-02
相关资源
最近更新 更多