so, whats quicker, byref or byval?
Take a look again at the example explanation I posted about strings and balls - we never make a copy of the ball, and establishing a new pointer to an existing ball is very fast. As noted, it is the pointer that is cloned, not the object data itself.
byref is quicker because you are actually passing the memory location, becareful when using byref because the changes made by the calling procedure will change the variable. ByVal is more safer but consume more memory and slower because it have to copy itself.
I'm sorry to say that nearly every statement in your post is incorrect. You talk about memory locations etc so youre clearly more interested in the low level than most people would be.
In .NET we have two areas for data. The stack, and the heap. Primitive (value) types like ints and booleans live entirely on the stack. Reference types (Objects) live on the heap. When a new object is made and placed on the heap, a primitive (e.g. a long) is placed on the stack, holding the numerical memory address where the object may be found in the heap. It is thus said to be a reference type, because it is accessed by a reference. We have a name,
myBall and this is known to be an long on the stack that holds a memory address of an object on the heap. We dont have direct access to the heap, we must first lookup where it lives by reading the contents of the variable on the stack. This is why it is a reference type, not a value type. It wouldnt be efficient to store value types on the heap because they are small enough to live on the stack and thus need no double leg from stack to heap.
When we pass that reference object to a method ByVal, the primitive value (pointer) on the stack is cloned and another pointer thus created on the stack, pointing to the object on the heap. If we re-point this pointer somewhere else, the original primitive remains pointing to the original object on the heap, and the cloned pointer now points to a new object on the heap.
When we pass something ByRef we do not make a clone of the pointer on the stack, we just reuse the same pointer. Thus, changing what this pointer points to (making a new object on the heap) changes what the original pointer points to.
One of the achilles heels with the ByRef/ByVal explanations is that people ask about strings. They say "When I pass a string ByVal it doesnt get changed, but when I pass it ByRef it changes/changes are retained"
The problem with citing string as an example (apologies to Mr McIlhinney, though I'm not bashing his explanation) is that strings are immutable; once created they cannot be changed. You may create a different string that is an altered version of the first, but the string content itself cannot change.
Thus people say that they pass their strings ByRef to retain changes to them - no, what actually happens is that the method that "alters" the string actually goes and creates a whole new string object on the heap, and points the old pointer to the new object. It *looks* like the string has changed content, but it has actually changed to a completely new string object.
Of course, because ByVal copies the pointer, any re-pointing of the copied pointer is lot when scope returns to the original.
Ends up, try not to use strings when creating examples that demonstrate mutating the object itself. Using strings to demonstrate a change to a whole new object is fine.
In my example you'll note I deliberately created a mutable object: we can deflate and inflate the ball. In either case of ref or val, the ball remained deflated after the method had finished.
As others have noted, do not use ByRef, until you fully appreciate what is going on with it. OO programs should be written such that objects do not fiddle with other object's data (my ball example should not directly fiddle with the air content.. it should call a method asking the ball to deflate) and that includes swapping the object for another object entirely
The situations where ByRef is necessary are rare, but an example exists in Double.TryParse
You make the variable pointer, then pass it to tryparse. The return value tells whether the conversion succeeded, and the passed variable is the result. Double.TryParse could not be established with ByVal:
Dim emptyDoublePointer As Double 'no object created, just a pointer
Double.TryParse("1234", emptyDoublePointer...)
MessageBox.Show(emptyDoublePointer.ToString())
--> 1234
String.Format works byval. We have to say:
Dim myUnfilledString as String = "I was filled with {0}"
Dim myFilledString As String = String.Format(myUnfilledString, "1234")
MessageBox.Show(myUnfilledString)
--> "I was filled with {0}"
MessageBox.Show(myFilledString)
--> "I was filled with 1234"
In this case we've had to capture the return value because String.Format takes its input string ByVal. If it took it byref it would re-point our original string. That might not be what we want if we want to re-use the unfilled string! Mcrosoft didnt use ByRef though they could have, and I'm glad they didnt because they would have been fiddling my original strings!
Actually, this has prompted a question in me. What happens if we pass a ReadOnly pointer as a ByRef argument (either directly or indirectly)? The compiler should disallow it, no?