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:
'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:
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:
Function MyStoredProcedure(i as Integer) As Dictionary(Of String, Object)
And then taken that string and that datareader and returned them:
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:
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:
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