none
What is the extra bracket telling .Net about the string variable RRS feed

  • Question

  • In the following code sample I would expect ABC to appear twice but the first time the variable is nothing. What does the extra bracket around myvar in the first call mean to the string variable when it is passed to the sub routine. Why is the string not returned?

    Module Module1
       
        Sub Main()
            
            Dim myVar As String

            MySub((myVar))
            Console.WriteLine(myVar)

            MySub(myVar)
            Console.WriteLine(myVar)

            Console.ReadLine()

        End Sub

        Public Sub MySub(ByRef myParam As String)
            myParam = "ABC"
        End Sub
    End Module

    Thanks

    Roy

    Wednesday, June 6, 2012 8:28 AM

Answers

  • Your extra parentheses mean that the default calling mechanism has been overridden.  Normally, the ByRef in the method signature would ensure the argument is passed ByRef.  But as you have enclosed the argument in brackets, it is passed ByVal instead.  When a reference type is passed ByVal and the called method assigns that variable to a new object (which a change to the value of a string always does) that new object is not accessible when the method returns because it was referenced from a copy of the original argument, and that copy has been discarded.

    See: http://msdn.microsoft.com/en-us/library/aa903254(v=vs.71).aspx

    "The procedure declaration determines the passing mechanism. The calling code cannot override a ByVal mechanism, but if an argument is declared with ByRef, the calling code can force the mechanism to pass by value by enclosing the argument name in parentheses in the call."


    • Edited by Acamar Wednesday, June 6, 2012 8:56 AM sp
    • Proposed as answer by John Anthony Oliver Wednesday, June 6, 2012 9:09 AM
    • Marked as answer by RoyBlea Thursday, June 7, 2012 12:22 AM
    Wednesday, June 6, 2012 8:55 AM

All replies

  • Roy,

    Your code is the same like this one 

    Module Module1
        Sub Main()
            Dim myVar As String
            Dim x = myVar
            MySub(x)
            Console.WriteLine(myVar)
            MySub(myVar)
            Console.WriteLine(myVar)
            Console.ReadLine()
        End Sub
        Public Sub MySub(ByRef myParam As String)
            myParam = "ABC"
        End Sub
    End Module

    The reference is in this case on x, In your original code it is somewhere on an internal temporally used string.


    Success
    Cor

    Wednesday, June 6, 2012 8:42 AM
  • That is the way to force to pass argument by value. See Force an Argument to Be Passed by Value (Visual Basic) to learn more. Done as in Cor's example.


    Wednesday, June 6, 2012 8:49 AM
  • Your extra parentheses mean that the default calling mechanism has been overridden.  Normally, the ByRef in the method signature would ensure the argument is passed ByRef.  But as you have enclosed the argument in brackets, it is passed ByVal instead.  When a reference type is passed ByVal and the called method assigns that variable to a new object (which a change to the value of a string always does) that new object is not accessible when the method returns because it was referenced from a copy of the original argument, and that copy has been discarded.

    See: http://msdn.microsoft.com/en-us/library/aa903254(v=vs.71).aspx

    "The procedure declaration determines the passing mechanism. The calling code cannot override a ByVal mechanism, but if an argument is declared with ByRef, the calling code can force the mechanism to pass by value by enclosing the argument name in parentheses in the call."


    • Edited by Acamar Wednesday, June 6, 2012 8:56 AM sp
    • Proposed as answer by John Anthony Oliver Wednesday, June 6, 2012 9:09 AM
    • Marked as answer by RoyBlea Thursday, June 7, 2012 12:22 AM
    Wednesday, June 6, 2012 8:55 AM
  • Be aware that some have written that it forces the passing byval and somebody has even proposed that as answer. 

    That is not the fact if a value is passed by val then there is only one thing passed, the value in this case. 

    MyVar 

    If a value is passed byref then there are two thing passed

    MyVar | The address of Var

    You pass currently 

    ? | The address of ?

    The effect is the same as passing byval because Myvar is not affected, but the field in ?

    The passing is however still ByRef

    To make that more clear in the sample

    Module Module1
        Sub Main()
            Dim myVar As String
            Dim x = myVar
            MySub(x)
            Console.WriteLine(myVar)
            Console.WriteLine(x)
            MySub(myVar)
            Console.WriteLine(myVar)
            Console.ReadLine()
        End Sub
        Public Sub MySub(ByRef myParam As String)
            myParam = "ABC"
        End Sub
    End Module
    x is the ? if you had enclosed ((myVar))


    Success
    Cor

    Wednesday, June 6, 2012 11:08 AM
  • Be aware that some have written that it forces the passing byval and somebody has even proposed that as answer. 

    That is not the fact if a value is passed by val then there is only one thing passed, the value in this case. 

    Hi Cor,

    Have you looked at the documentation link that Acamar posted?

    http://msdn.microsoft.com/en-us/library/aa903254%28v=vs.71%29.aspx

    Even the documatation on that page states the following,

    "The procedure declaration determines the passing mechanism. The calling code cannot override a ByVal mechanism, but if an argument is declared with ByRef, the calling code can force the mechanism to pass by value by enclosing the argument name in parentheses in the call"

    '

    Forum user MasaSam also pointed out the documentation on this subject, look here please.>>

    http://msdn.microsoft.com/en-us/library/chy4288y

    '

    Consider too that if you pass a reference type ByVal you can also change its property values.

    '

    Have you also seen this discussion? >>

    http://social.msdn.microsoft.com/Forums/en/vblanguage/thread/a7e4f7da-c1e1-4228-b634-04a8132cc4e1




    Regards,

    profile for John Anthony Oliver at Stack Overflow, Q&A for professional and enthusiast programmers

    Click this link to see the NEW way of how to insert a picture into a forum post.

    Installing VB6 on Windows 7

    App Hub for Windows Phone & XBOX 360 developers.

    Wednesday, June 6, 2012 11:36 AM
  • Good links there, John and Acamar.

    I think another important thing is 'why you would want to do this', which is pointed out in the documentation: it may be sometimes necessary to prevent the passed variable to a method from being modified.

    Of course, if the method is within ones own assembly, you could make it ByVal, but it depends on what the method does. You may both simultaneously want a method to modify the passed variable and sometimes not. If the method is in an external assembly then there is no choice. The TryParse methods are some such methods where you may not want the passed variable modified.


    Stephen J Whiteley

    Wednesday, June 6, 2012 11:58 AM
    Moderator
  • Did you see the documentation is from 2003 and then still not as clear as it can be.

     The calling code cannot override a ByVal mechanism, but if an argument is declared with ByRef, the calling code can force the mechanism to pass by value by enclosing the argument name in parentheses in the call. 

    Exactly the same as I show, by passing another field (the result of the procedure) the original value is not changed.

    But the value is still passed by ref, in other words the address is added. 

    The method is not changed, then it is not OOP anymore, there is done a trick to get the same result.

    I agree that it is not the best description we have seen on MSDN.

    Success
    Cor





    Wednesday, June 6, 2012 12:04 PM
  • Be aware that some have written that it forces the passing byval and somebody has even proposed that as answer. 

    That is not the fact if a value is passed by val then there is only one thing passed, the value in this case. 

    MyVar 

    If a value is passed byref then there are two thing passed

    MyVar | The address of Var

    There is only ever one thing passed.  If the argument is passed ByVal then the value of the variable is passed.  If the argument is passed ByRef then a reference ('pointer') to the variable is passed.

    The effect is the same as passing byval because Myvar is not affected, but the field in ?

    The passing is however still ByRef 

    The passing is not ByRef.  If the argument is enclosed in quotes, the argument is passed ByVal.   If the argument is a value type this means a copy of the value of the variable is passed.  If the argument is a reference type then this means that a copy of the reference ('pointer') is passed.   This reference can be used to refer to the original object, but it is stil a copy of the variable value, and it is discarded when the called routine ends.

    This effect of enclosing the argument in brackets is the same as it was in VB6 and the same as it is in VB Script.

    Wednesday, June 6, 2012 12:39 PM
  • Cor

    If a value is passed byref then there are two thing passed

    Nonsense.

    Only one thing is ever passed: the value or the address, never both. That is elementary stuff that I'd have thought you knew. :)


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

    Wednesday, June 6, 2012 3:11 PM
  • This bug took me a long time to track down as initially I did not spot the extra brackets.

    The conversion program placed brackets around the variable. But to be fair to the conversion program the original VB6 code passed a string stored within a structure inside an array to fetch the value.     (sigh)

    ProfileKey LstItem.Index - 1, Keys(KeyCount).Profile

    was converted to

    ProfileKey(LstItem.Index - 1, (Keys(KeyCount).Profile))

    My predecessors seemed to adore arrays of structures but hate functions, unless the function could be disguised as a variable  :-(

    Thanks everyone for the help.
    Thursday, June 7, 2012 12:50 AM