tags:

views:

1898

answers:

8

What are the things to consider when choosing between ByRef and ByVal.

I understand the difference between the two but I don't fully understand if ByRef saves resources or if we even need to worry about that in the .Net environment.

How do you decide between the two if the functionality doesn't matter in a situation?

+7  A: 

ByVal should be your "default". Use it unless you have a specific reason to use ByRef

Kevin
+4  A: 

Use "ByRef" only if the parameter is "output" parameter. Otherwise use "ByVal". Using "ByRef" on parameters which explicitly should not return values is dangerous and can easy generate bugs.

TcKs
A: 

Deleted

lubos hasko
No, by default all types are passed ByVal. Just remember that ByVal for reference types is passing the *reference* by value, not the object.
Jon Skeet
Not true, default for everything is byVal. What you are referring to is the fact that the "value" you are passing with a class is in fact a refereence. (it's a reference type)
Charles Bretana
@Charles, yes you're right, I've never done any work in VB.NET and misunderstood the question.
lubos hasko
@Jon, so what happens if you pass *reference type* ByRef? Does it even make any sense if it's already passing reference, not the object itself?
lubos hasko
lubos see my post below to answer this question
Charles Bretana
Yes, it makes perfect sense. It means that the variable's value can be changed. See http://pobox.com/~skeet/csharp/parameters.html for an example.
Jon Skeet
@Jon, I see what you mean now (from example 6), I get this. There might be very limited practical use for this behavior, I don't think I will ever use it but still, it's good to know just in case. thanks.
lubos hasko
As others have said above, this capability (passing reference types byref) is seldom needed - it is useful when you need to control "which" class is in use by a method, and you have another method that "figures out" which instance of the class to use, and But you can't just return the new reference
Charles Bretana
+13  A: 

There's a lot of misinformation around about this. The main thing is that you understand the difference between value types and reference types, and the difference between pass by value and pass by reference.

You almost always want to pass by value. Passing by reference is almost always for "I want to return more than one result, and not just by adding things to a list which is passed in." The classic example of a method using pass-by-reference is Int32.TryParse where the return value is a success/failure, and the parsed value is "returned" by an out parameter.

Jon Skeet
+1. Passing by ref and changing inside a method that returns void is a common 'mistake' in my mind - it's misleading as to what the method is doing.
Kon
Many developers are still prone to use this pattern - maybe because their background is from C++, or in COM, where ret vals were always error codes and this pattern was necessary ?
Charles Bretana
+1  A: 

Passing an object ByVal in .net does not make a copy of the object and does not consume more resources then ByRef, A pointer is still passed through to the function. The runtime just ensures that you can't modify the pointer in your function and return a different value for it. You can still make changes to the values within the object and you will see those changes outside the function. That is why ByRef is uses so rarely. It is only needed when you want a function to change the actual object that is coming back; hence an output parameter.

DancesWithBamboo
Is this true? Why did it get voted down? Maybe I didn't ask the question properly because this is more along the line of the answer I was looking for.
ctrlShiftBryan
It is technically true, but very misleading. When passing an object byVal, the "object" is not copied, but the object's address IS copied, and passed to the called method. When passing byRef, the object's address is NOT copied, the address of the addesss is passed.
Charles Bretana
+8  A: 

The default is byValue for ALL types, but it is important to understand what the two options mean for a "reference type" (a class) as opposed to a value type. (structs).

For a reference type, if you declare a reference type variable in a method, that variable is a memory location in the stack frame of the method. It is not on the heap. When you initialize that variable (using new or a factory, whatever), then you have created an actual object on the heap, and the address of that object is stored in the declared reference variable in your methods stack frame.

When you pass a reference type to another method byVal, you are creating a copy of the address stored in the calling methods stack and passing the copy of that value (the pointer address) to the called method, where it is stored in a new memory slot in the called methods stack. Inside the called method, the new cloned variable points directly to the same object on the Heap. So using it can change the properties of the same object. But you cannot change which heap object the original reference variable (on the calling methods stack) points to. If, in the called method I write

  myVar = new object();

The original variable in the calling method will not have changed to point to a new object.

If I pass a reference type byRef, otoh, I am passing a pointer to the declared variable in the calling methods stack (which contains a pointer to the object on the heap) It is therefore a pointer to a pointer to the object. It points to the memory location on the calling methods stack, which points to the object on the heap.
So now, if I change the value of the variable in the called method, by setting it to a new object(), as above, since it is a "refereence" to the variable in the calling method, I am actually changing which object the variable in the calling method is pointing to. So After the called method returns, the variable in the calling method will no longer be pointing to the same original object on the heap.

Charles Bretana
This is certainly what I've learned in the Java world but I'm not sure it is so in .Net?
ctrlShiftBryan
I'm not a Java guy, but I had heard that Java did not even have value types.. That every variable was a reference type... Is that wrong?
Charles Bretana
Yes, it's wrong. Java has value types. What it doesn't have is user-defined value types.
Jon Skeet
ahh, so, you mean things like int, short, ulong, decimal, char, etc... are implemented as value types, on each methods stack frame, but any custom user defined type is implemented as ref type on heap ?
Charles Bretana
Yes, although bear in mind that value types end up on the heap as part of other objects too. See http://pobox.com/~skeet/csharp/memory.html
Jon Skeet
yes, what we call a "field" in .Net... a variable declared within a type (class or struct) which is outside of any method, property or constructor...
Charles Bretana
A: 

I'm not sure I asked the question properly.

Is there a .Net equivalent to passing something ByRef as ReadOnly(As you would in Java)? To save resources?

ctrlShiftBryan
Please show the Java syntax, and we'll say whether or not you could do the same in C#. Bear in mind that Java is purely pass-by-value...
Jon Skeet
In other languages in order to save resources large objects can be passed by read only reference in order to save resources. It acts like a passed by value reference but does not make a copy.
ctrlShiftBryan
Yes, but there's nothing like that in Java... that's why I asked for a Java example.
Jon Skeet
A: 

Marking certain arguments as ByRef shows the user of your function that the variable allocated to that argument will be modified.**

If you use ByRef for all args, there'll be no way to tell which variables are modified by the function, and which are just read by it. (apart from peeking inside the function source!)

Jenko