Why default to ByVal?

froodley

Active member
Joined
Apr 20, 2010
Messages
26
Programming Experience
1-3
Hey, folks,

Just kind of curious about something: why does VS (vb and C#) default params to pass-by-value?

I almost never need or want to pass anything by value. Maybe this is some reflection on the way I code. I would never manipulate a value type param directly; i would just return the new value from a private variable... and I just don't see the need to do the background work all the time to add copies of everything to the stack. Why wouldn't I just about always want to pass-by-ref? This seems like it's backwards to me.

Someone enlighten me!
 
As far as I know all the top languages: Java, PHP, C/C++, Python, Perl, Ruby, etc... all default to passing ByVal.

I'm not sure about your style of programming but I rather like it that things are passed ByVal instead of ByRef by default as there's extremely rare times when I ever need to pass ByRef anyways.
 
ByRef allow the method to dereference the callers object, something that is a code security risk, and something one in most cases would want to avoid. The cases where ByRef is required is very rare and usually a function is used instead since is more logically implies returning a new object. Similar to the conventions and what most people would say, I can't recall a single time I have ever needed to use a ByRef parameter (hmm perhaps once). I think when you say you always want to pass ByRef that you don't understand how ByVal works, but I do think you know the difference between value types and reference types. See also Passing Arguments by Value and by Reference
I almost never need or want to pass anything by value.
The point, from callers perspective, is that you almost never need the ability ByRef gives you.
I just don't see the need to do the background work all the time to add copies of everything to the stack.
"Everything" is never copied to stack, and this has basically nothing to do with ByVal/ByRef, here's an article that explains about Heap and Stack: C# Heap(ing) Vs Stack(ing) in .NET: Part I
 
Thanks :D

Thanks for the feedback; it was helpful.

I think I had gotten in the habit of using byref because I didn't want to incur overhead during iteration by having to make copies of everything. I realize it's just making copies of the reference for reference types, but doesn't this still incur some overhead?

So really the only time you use byref is if you are planning to change the value of a value type directly in the method? That's something I don't do anyway as a rule (I would use a function).

Since I have always passed value types byval (to avoid working on them directly), and reference types byref (to avoid copying the reference to the stack), I guess I can just change to the other way in the future? Or am I missing something :p

Thanks!
 
So really the only time you use byref is if you are planning to change the value of a value type directly in the method?
Yes, or dereference the caller object (ie assign a new object to the out parameter).
but doesn't this still incur some overhead?
Yes, the overhead of one integer allocation to keep the reference address. This extra memory usually has no practical significance, but the assurance for the caller that the original referenced object is not changed is usually really important. It is also possible for caller to force ByVal when ByRef is declared to avoid such possible modifications that is deemed uncalled for (There's a 'how to: force...' link in second article).
 
So really the only time you use byref is if you are planning to change the value of a value type directly in the method?

No, the only time you use ByRef is when you intend to change the passed-in variable to point to a completely new object in memory. One such example is the code that is generated in a TableAdapter for accessing database procedures

Suppose I have a database stored procedure that takes in an int and has 2 OUTPUT parameters that will be set to a string and a cursor (a set of rows)
When I conenct to this using the DataSet designer, it makes a Function for me that looks like:

VB.NET:
'theCursor will actually be a DataReader, but its presented as Object and needs a cast
Sub MyStoredProcedure(theInt as Integer, ByRef theString as String, ByRef theCursor as Object)

Why does it do this?

Because I call it in my code like:

VB.NET:
Dim s as String = "hello"
Dim o as Object
myTableAdapter.MyStoredProcedure(1234, ByRef s, ByRef o)
(Maybe byref in vb isnt needed here.. I work in C#, and we have to declare "ref" and "out" when we pass in, to prove to the compiler we understand that it's a pass by reference)

If the parameter wasnt ByRef, there would be no way for the procedure to do its work, get the string and the cursor, and then point MY variables that I made in MY code, to the objects. After finishing the procedure, my string would still be "hello"

If they were ByVal, the Function would assign to a copy of the variable, which would go out of scope.


ByRef is sometimes called a "lame way to return multiple values from a Function"

Sure, our database code could have done this instead:

VB.NET:
Function MyStoredProcedure(i as Integer) As Dictionary(Of String, Object)

And then taken that string and that datareader and returned them:
VB.NET:
Dim d as Dictionary(Of String, Object) = myTableAdapter.MyStoredProcedure(1234)
Dim s as String = DirectCast(d("theString"), String)
Dim r as DataReader = DirectCast(d("theReader"), DataReader)

In this case the Dictionary is just a "poor man's custom class", probably Microsoft would have invented this:
VB.NET:
Class MyStoredProcedureOutputs
  Public Property theString As String 'get/set code omitted for brevity
  Public Property theReader As Object 'get/set code omitted for brevity
End Class
Then populated and returned that


There are always more ways than one to skin a cat, and I suspect that your extensive use of ByRef could(and should) nearly entirely be replaced by ByVal because your ByRef habit is a holdover from a time when you didnt understand how the mechanism worked.. You thought you were using ByRef to avoid massive copy operations of all your memory data, but really the only thing being copied is a pointer

ByVal object data itself is directly manipulated:

VB.NET:
Sub PutSomethingInAStringBuilder(sb as StringBuilder)
  sb.AppendLine("Something")
End Sub

...

Dim sb as New StringBuilder
PutSomethingInAStringBuilder(sb)
'sb now contains "Something"

Just because you copied the pointer, youre still changing the original data. If ByVal truly did copy the data, you wouldnt even see "Something" in your stringbuilder

For this reason you SHOULD switch to ByVal exclusively, except when you have a really really good reason to point someone else's pointer to something you made

Imagine how irked you'd be if someone elses code replaced your objects with its own; you have a nice object that it's taken you ages to create and populate, and you pass it into a ByRef parameter of a method written by some idiot, and he just swapped your nice, painstakingly populated object for a whole new one, destroying your work. That's why we don't use ByRef - it's so rare that you want to rip someone else's pointer off their data is attach it to our own because we don't really have the "moral" right to do so ;)
 
Back
Top