Why are objects passed by reference?
Doesn't C# send the objects themselves? So unless it's some kind of swap function for primitive typed variables - why would I send an object by reference?
C# doesn't pass the objects themselves. C# passes whatever's in the stack. For value types that are locally-scoped and thus live on the stack, the value is passed down to the next level of the call stack. For all other objects, the data is on the heap and a reference to the heap address is stored on the stack, and is passed around.
In either case, the data that resides on the stack, whether that's the data you care about or a reference "pointer" to the data you care about, is not changed, because when it is passed, it is copied to a new location on the stack and that value is what is manipulated (and then discarded when the method exits and that frame pops off the call stack). If you pass a value type to a method that changes the value, when that method returns to its caller the value will be unchanged, because that copy of the data was never touched by the method. If you pass a reference type, it is the reference that is copied. This means that the data on the heap, pointed to by the reference, can be altered and that will change the data for the caller. BUT, if the passed parameter is reinitialized or otherwise assigned to a different reference, that change will be reverted when the method returns, because that is a change to the reference to the object, which was passed "by value" and doesn't affect the caller's copy of that reference.
For proof, run this test in NUnit:
So given that default behavior when not using
Behind the scenes, when you use or alter the passed
C# sends references to objects all the time. That is, when you do
When you use the
So, just like
Okay, now that we've gotten past that, let's contend with the question of why the hell do this.
Well, the short answer is, do not use the
There are several reasons for this rationale. First of all, keeping the number of function returns at a minimum helps comprehension. It reduces the number of diverging pathways your code can possibly take.
Then, passing things by reference opens up a whole slew of nasty typing and mutability problems. Let's say I have an instance
It is necessary to use when you want a method to modify a value type or modify a reference to a reference type, The most commmon reason for doing either of these in code I've seen is interop with C || C++ libraries, e.g.
In pure managed code it tends to be rarer to need ref or out as you mainly use reference types which already give you references to objects rather than copies of objects like value types do. i.e. one level of indirection is all you need most of the time (indeed if you need ref a lot you may be a three star programmer ;)
When you pass an object by reference, you can change the value of the reference.
Let's say you have a Person class:
You also have these functions:
And then you have this console app:
The output will be:
As you can see, assigning a new value (as opposed to changing properties) or setting it to null (which is also changing the value) of the reference itself, requires you pass by reference.
For a better and more detailed explanation, you can have a look at this article by Jon Skeet.
Making a deep copy of an object is a potentially very expensive operation in terms of both memory and CPU. In some cases (
On the other hand, making a deep copy of the value of a primitively-typed variable is quite cheap, and in some cases (for example, immutability of strings) comes essentially for free.
Generally, I feel that functions should not touch their input parameters unless the caller actually wants it to. An easy way to ensure that the caller at least is aware that the callee might alter the input is to require passing by reference, either
Send objects by reference when you want to have the possibility of modifying the original object. Otherwise, send by value if you just need the value of the object.
Passing by reference happens all the time and isn't just for swap functions.