locked
ByRef oddity RRS feed

  • Question

  • In the code block below, the commented out line "i+=1" properly does not compile since Shared i is ReadOnly.  But the two go() calls compile cleanly and run without exception, and that is by design.  VB treats ByRef like ByVal when the argument is not modifiable.  I would prefer that the compiler give a warning when a non-modifiable variable is passed ByRef to a sub/function.  I think it odd that "i+=1" and go() behaviors are so different.  Any thoughts?

    Public Class test
      Public Shared ReadOnly i As Integer = 1
      Public Shared Sub go(ByRef x As Integer)
        x += 1
      End Sub
      Public Shared Sub test()
        'i += 1 ' error BC30064 'ReadOnly' variable cannot be the target of an assignment.
        go(i) ' runs without exception, shared i remains 1
        go(8) ' runs without exception
      End Sub
    End Class
    

    Sunday, February 3, 2019 10:15 AM

Answers

  • I surrender
    • Marked as answer by amercer Sunday, February 3, 2019 8:44 PM
    Sunday, February 3, 2019 8:44 PM

All replies

  • Hello,

    Question, is there a problem you are attempting to solve outside of how the field is being handled or simply experimenting?


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Sunday, February 3, 2019 11:13 AM
  • Hi,

    I think what you mean should be to set the field i to be unreadable or writable.

    Public Class Form1
        Public Shared _i As Integer = 1
    
        Public WriteOnly Property i As Integer
            Set(ByVal Value As Integer)
                _i = Value
            End Set
        End Property
    
        Public Shared Sub go(ByRef x As Integer)
            x += 1
        End Sub
        Public Shared Sub test()
            'i += 1 ' error BC30064 'ReadOnly' variable cannot be the target of an assignment.
            'go(Form1.i) ' runs without exception, shared i remains 1
            go(8) ' runs without exception
        End Sub
    End Class

    Best Regards,

    Alex


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Proposed as answer by IronRazerz Sunday, February 3, 2019 12:05 PM
    • Unproposed as answer by amercer Sunday, February 3, 2019 8:44 PM
    Sunday, February 3, 2019 11:29 AM
  • What prompted my comment was chasing down a bug.  The wrong variable was changed to ReadOnly, a confusing debugging session ensued, and I finally saw the mistake.  VB quietly caused the effect of a sub call to be nullified - the assignment to the ByRef variable disappeared.  I just thought a better design choice would be a compiler warning rather than in effect changing ByRef to ByVal.  It is hard to imagine a setting where passing a constant ByRef would ever be correct (the go(8) case in my OP).
    Sunday, February 3, 2019 12:11 PM
  •  As Alex has said,  you need to make i a ReadOnly Property and then set the property backing field inside the sub,  not the actual property.  Notice the underline _ character in front of i (shown below),   that is how the private property backing fields are declared by VS behind the scene if you do not add the Get and/or Set methods to the property yourself.

        Public Shared ReadOnly Property i As Integer = 1
        Public Shared Sub go(ByRef x As Integer)
            x += 1
        End Sub
        Public Shared Sub test()
            _i += 1 ' error BC30064 'ReadOnly' variable cannot be the target of an assignment.
            go(i) ' runs without exception, shared i remains 1
            go(8) ' runs without exception
        End Sub


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Sunday, February 3, 2019 12:22 PM
    Sunday, February 3, 2019 12:15 PM
  • This property issue is beside the point.  My comment is about different treatment of an assignment statement.  When coded inline, eg as i=i+1 where i is readonly, the compiler diagnoses it.  When a readonly is passed byref, you get a different result, namely the code compiles and the byref attribute is counterfeited/ignored.  Coding workarounds are not what I'm looking for.  What I am looking for is support for my position or a reason why I am wrong.
    Sunday, February 3, 2019 12:43 PM
  • This property issue is beside the point.  My comment is about different treatment of an assignment statement.  When coded inline, eg as i=i+1 where i is readonly, the compiler diagnoses it.  When a readonly is passed byref, you get a different result, namely the code compiles and the byref attribute is counterfeited/ignored.  Coding workarounds are not what I'm looking for.  What I am looking for is support for my position or a reason why I am wrong.

    For support you can ask by the feedback button, below is in VS2017, prior versions before VS2015 will be in a different location. Depending on the issue and how well you ask dictates responses. If you go this route give variable names better names and longer than one character.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Sunday, February 3, 2019 1:22 PM
  • This property issue is beside the point.  My comment is about different treatment of an assignment statement.  When coded inline, eg as i=i+1 where i is readonly, the compiler diagnoses it.  When a readonly is passed byref, you get a different result, namely the code compiles and the byref attribute is counterfeited/ignored.  Coding workarounds are not what I'm looking for.  What I am looking for is support for my position or a reason why I am wrong.

     Hmmm...  that is strange it lets you build without showing you the error.  I would guess that maybe you might have some VS Exception Settings or maybe some other Settings in the VS Options that have been turned On or Off somehow.  If I paste your code into VS as it is,  it does not build because,  it is showing the problem with i being ReadOnly,  as seen in the image below.

     The i has the red line under it and shows the following error before I can even build it  ->  BC30064    'ReadOnly' variable cannot be the target of an assignment.  It does this no matter if I use  "i += 1"  or if I use "i = i + 1".  A ReadOnly variable is just that,  you can only read the value from it,  you can not change the value of it.  That is true no matter if you pass it ByRef or ByVal.

     

     However,  maybe I am just not understanding what answer you are looking for?  8)

     PS - It would not make sense to pass a ReadOnly variable ByRef to begin with.  Using ByRef would give you no more access to the variable than passing it ByVal.  You still would only be able to get/read the variable value,  not assign new values.


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Sunday, February 3, 2019 1:42 PM
    Sunday, February 3, 2019 1:34 PM
  • By the way, this behaviour is valid according to Language Specification (Version 11, §9.2.5.2, “Copy-in copy-back”), but it is not clear how to enable a warning message.

    Sunday, February 3, 2019 1:59 PM
  • I surrender
    • Marked as answer by amercer Sunday, February 3, 2019 8:44 PM
    Sunday, February 3, 2019 8:44 PM