【问题标题】:Calling function with property as byref argument causes set method call使用属性作为 byref 参数调用函数会导致 set 方法调用
【发布时间】:2019-03-08 11:28:56
【问题描述】:

当调用一个以属性为参数的函数时,该属性的 set 方法在函数调用之后执行。

如果您尝试使用 ref 将属性传递到函数中,如果在 c# 中完成,则会抛出编译器错误,但在 vb.net 中会发生这种情况。这是一个错误吗?怎么回事?

Module Module1

    Private _testProp As Integer
    Property testProp As Integer
        Get
            Return _testProp
        End Get
        Set(value As Integer)
            Console.WriteLine("changed TestProp to " & value.ToString())
            _testProp = value
        End Set
    End Property

    Private Sub testFunction(ByRef arg As Integer)
        Console.WriteLine(arg)
    End Sub

    Sub Main()
        Console.WriteLine("explicit set to 5 in main")
        testProp = 5
        Console.WriteLine("calling function")
        testFunction(testProp)
        Console.ReadKey()
    End Sub

End Module

输出:

在 main 中显式设置为 5
将 TestProp 更改为 5
调用函数
5
将 TestProp 更改为 5

【问题讨论】:

  • 由于是通过ByRef,方法~could~改变原来的值,但实际上不知道值是否改变;因此它在方法调用之后更新属性以确保它具有最新值。看起来像“ByRef by Illusion,还有一个你需要注意的怪癖?我只是在这里猜测,因为我找不到任何关于此的实际文档。=/
  • 因为通过引用传递引用类型使得被调用的方法能够替换调用setter的对象。被调用的方法“可能”改变这个值,它可能不太清楚,所以在实际使用它之前就已经设置好了。
  • TBH,我会阅读如何传递参数 herehere,显然 不是错误,只是一个误解。
  • @Çöđěxěŕ 不幸的是,帮助中似乎没有记录这种行为。我已经检查了你的两个链接。
  • @Craig 我的链接不正确(复制粘贴错误),但通常 ByRef 属性指定参数的值将在方法执行完成时更新......所以在这个如果属性设置器在方法中使用之前就被调用(创建新对象)......这样做实际上很好,当您传递属性并且另一个线程在您的方法获得您 期待,现在不一样了;因此为什么实际调用了 setter。

标签: vb.net properties function-call byref


【解决方案1】:

将属性传递给ByRef 参数会导致该属性通过复制输入/复制输出传递。 VB 语言规范规定,

复制入回。如果传递给引用参数的变量的类型与引用参数的类型不兼容,或者如果非变量(例如属性)作为参数传递给引用参数,或者调用是后期绑定的,然后分配一个临时变量并将其传递给引用参数。传入的值会在方法被调用之前被复制到这个临时变量中,当方法返回时会被复制回原来的变量(如果有并且是可写的)。

所以这显然是设计使然,而不是错误。

【讨论】:

  • 这是一个相当讨厌的设计。我认为每次更改属性的引用时都会调用 set 函数,而不是它不仅被调用一次,而且在函数返回时总是被调用一次。如果您说的是真的,这意味着如果在函数调用中更改了属性的引用,则计算属性更改次数的属性集不会更新?
  • 这绝对会给粗心的人带来麻烦。我记得在我维护的软件中修复了一个与此行为相关的错误。
  • @FalcoGer,copy-back 可以通过将ByRef 参数包装在一组括号中来防止。即MethodName((byrefArgument))。请参阅:How to: Force an Argument to Be Passed by Value (Visual Basic)Passing ReadOnly Properties of Controls ByRef 了解更多信息。
  • 你在哪里找到这个克雷格的?
  • @Idle_Mind,在 VS2017 之前,Visual Basic Language Specification 的副本包含在安装中(即:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VB\Specifications\1033\ Visual Basic 语言规范.docx)。现在它在 GitHub 上,如先前链接中所示。具体报价可以是found on this page
猜你喜欢
  • 1970-01-01
  • 2015-09-16
  • 1970-01-01
  • 2016-06-09
  • 1970-01-01
  • 2016-07-06
  • 2016-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多