3

I have some simple code and I understand what it does but not why. I have a Sub and it calls another Sub called CheckIfNothing(oList). oList is a List(Of String). The Sub CheckIfNothing checks each String and if it it Nothing it will make it "". This is the code:

Public Function GiveList(oList As List(Of String))

    CheckIfNothing(oList)

    Return oList
End Function

Public Sub CheckIfNothing(oList As List(Of String))

    For Each s As String In oList
        If s Is Nothing Then
            s = ""
        End If
    Next

End Sub

So in GiveList I call CheckIfNothing and I don't return anything from CheckIfNothing and still, the oList in GiveList has no Strings that are Nothing.

I always thought you had to return the value you changed in the called function and set the value again in the sub you call the function in like this: oList = CheckIfNothing(oList). CheckIfNothing would be a function in this case.

Why isn't this necessary, and is this only in VB.NET or also the case in C#?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Krowi
  • 1,565
  • 3
  • 20
  • 40
  • http://stackoverflow.com/a/5744818/2864740 (the problem posed in this question does not appear to be related to ByRef or ByVal as that affects the *calling semantics*, but rather about the use of the erroneous `s = ""` statement) – user2864740 Mar 18 '14 at 19:28
  • So what's the actual problem you are trying to solve? This is a famous AB problem. Instead of asking about problem A you have, you are asking about attempted solution B and why it failed. – Victor Zakharov Mar 18 '14 at 19:48
  • 1
    I have no problem. I'm asking for an explanation why it isn't necessary to do this: `oList = CheckIfNothing(oList)`. Bradley Uffner posted a comment in the other post: "Keep in mind that Reference Types are ALWAYS passed by reference, even if you specify ByVal in the function signature. – Bradley Uffner" which I think is the correct answer. – Krowi Mar 18 '14 at 19:51
  • There is no problem. He is asking why it behaves the way it does. – SoftwareCarpenter Mar 18 '14 at 19:53
  • Reference types are passed by value by default, same as value types. ByVal is the default, always, period, no exceptions. However, the value of a reference type is a reference. So it may appear as if you are passing ByRef. How you can tell? Simple - try to assign to a ByVal argument - notice nothing changed when you went out of your function. Try ByRef - now it changed. There is no rocket science here. – Victor Zakharov Mar 18 '14 at 19:54
  • The default is ByVal in .NET, is and has always been. [Source](http://social.msdn.microsoft.com/forums/en-US/c331b22f-8d64-4308-8dec-edcb792389e8/byval-and-visual-studio-2010-sp1). [Another source](http://msmvps.com/blogs/carlosq/archive/2011/03/15/vs-2010-sp1-changing-quot-byval-quot-vb-net-code-editor-experience.aspx). – Victor Zakharov Mar 18 '14 at 20:08

1 Answers1

2

Maybe this will help explain your question. It is from MSDN regarding Visaul Basic 2013.


When passing an argument to a procedure, be aware of several different distinctions that interact with each other:

•Whether the underlying programming element is modifiable or nonmodifiable

•Whether the argument itself is modifiable or nonmodifiable

•Whether the argument is being passed by value or by reference

•Whether the argument data type is a value type or a reference type

For more information, see Differences Between Modifiable and Nonmodifiable Arguments (Visual Basic) and Differences Between Passing an Argument By Value and By Reference (Visual Basic).

This code is an example of how you can use () around your parameter to protect it from being changed.

Sub setNewString(ByRef inString As String)
    inString = "This is a new value for the inString argument."
    MsgBox(inString)
End Sub
Dim str As String = "Cannot be replaced if passed ByVal" 

' The following call passes str ByVal even though it is declared ByRef. 
Call setNewString((str))
' The parentheses around str protect it from change.
MsgBox(str)

' The following call allows str to be passed ByRef as declared. 
Call setNewString(str)
' Variable str is not protected from change.
MsgBox(str)

Passing Arguments by Value and by Reference (Visual Basic) 2013

SoftwareCarpenter
  • 3,835
  • 3
  • 25
  • 37
  • Great answer, thank you. Would it be possible to add some little example when the argument is passed as a value when nothing is specified? – Krowi Mar 18 '14 at 19:28
  • Sure. Do you want it to show the result if the sub parameter was being passed in by val? – SoftwareCarpenter Mar 18 '14 at 19:32
  • 1
    Keep in mind that `Reference Types` are ALWAYS passed by reference, even if you specify `ByVal` in the function signature. – Bradley Uffner Mar 18 '14 at 19:39
  • @SoftwareCarpenter: My code works as intended. I'm really just wondering why it works. I also checked your link. I get how the List is passed ByRef and that is the reason why the code works. I'm just a little confused with "The argument is passed by value if it is enclosed in parentheses, and if the parentheses do not apply to the parameter list. The argument is also passed by value if the variable sent as an argument is in a class." I checked your link but it doesn't explain this last part that good imo. – Krowi Mar 18 '14 at 19:39
  • @Bradley Uffner: so even if `Public Sub CheckIfNothing(ByVal oList As List(Of String))` had the `ByVal`, it would work like in my OP? Now if it was an `Integer`, `ByVal` and `ByRef` would matter? – Krowi Mar 18 '14 at 19:41
  • 1
    Correct. `List` is a "Reference Type" so it is always passed byRef. the byRef and ByVal only affects the Intrinsic types like Integer, boolean, etc... It also affects Structures. `String` is a special case; it is a reference type, but behaves like a value type in most cases. – Bradley Uffner Mar 18 '14 at 19:45
  • -1. ByVal is the default, not ByRef. http://stackoverflow.com/questions/9207620/why-is-it-not-necessary-to-indicate-byval-byref-anymore – Victor Zakharov Mar 18 '14 at 19:47
  • @Bradley Uffner: Thank you for the explanation. Makes sense now :) – Krowi Mar 18 '14 at 19:48
  • @BradleyUffner: This is not correct either. Classes can be passed ByVal and ByRef, it affects whether you can reassign the variable. Nothing more, nothing less. No matter if you are passing value or reference type. – Victor Zakharov Mar 18 '14 at 19:50
  • Why did I get down voted. Byref is the default is none is specified. – SoftwareCarpenter Mar 18 '14 at 19:50
  • @SoftwareCarpenter: No it's not - see my comment above. – Victor Zakharov Mar 18 '14 at 19:51
  • There is nothing wrong with his code. He is asking why his list gets updated without having to return the list and set to a new list. Try it for yourself. If you set it to Byval it does not get updated. – SoftwareCarpenter Mar 18 '14 at 19:52
  • @SoftwareCarpenter: I am not arguing about the question. I am saying is that ByRef is NOT the default. ByVal is. You can google, you can try it yourself. Bottom line is that fundamentally wrong statements should not be spread to new developers, IMHO. – Victor Zakharov Mar 18 '14 at 19:56
  • @Neolisk See MSDN article. If nothing is specified then it is by ref. Also run the code yourself. – SoftwareCarpenter Mar 18 '14 at 19:59
  • @SoftwareCarpenter: The article you linked is for VBScript. In VB.NET the default is and has always been ByVal. [Source](http://social.msdn.microsoft.com/forums/en-US/c331b22f-8d64-4308-8dec-edcb792389e8/byval-and-visual-studio-2010-sp1). – Victor Zakharov Mar 18 '14 at 20:07
  • @Neolisk You are correct. I see where it was changed to byval by default. Do I just delete my answer? – SoftwareCarpenter Mar 18 '14 at 20:20
  • @SoftwareCarpenter: No need, as there are no other answers to the question. Change it to be correct, as far as ByVal vs ByRef. I'll remove my downvote. – Victor Zakharov Mar 18 '14 at 20:23