|Deep C# - Passing Parameters|
|Written by Mike James|
|Thursday, 19 November 2015|
Page 1 of 4
Passing parameters is easy as it always works in the same way, but the effects aren't always the same. It can be confusing and even error prone unless you understand how it all works. So does C# pass by value or reference?
This is Chapter 2 of our ebook on C# - a work in progress.
The difference between a value and a reference type can be dangerous when passing parameters to a method. Exactly what is passed and how it behaves confuses even experienced programmers who ask questions along the lines of - is this pass by value or pass by reference or pass by ...
The rule is very simple, by default value types are passed by value and reference types are also passed by value!
That is by default C# always uses pass by value.
However when you pass a reference variable by value it look a lot like passing by reference. This sounds complicated but as long as you keep the idea of a value and a reference clear its not so difficult.
Pass Value By Value
Consider first passing a value type by value.
We have the usual PointV struct (see Chapter One) and a method that simply sets one of its fields to a value:
Notice that the method has nothing to do with the struct - it is part of some other object.
Next we create an instance of the struct using new to make sure its fields have been initialised:
This results in a value variable b with it’s x field set to 5 as shown
If we now call MyMethod with b as parameter:
a new local variable a is created and initially set to the same value as b, then a.x is set to 10.
The result is a local variable with its x field set to 10 as shown
Finally MyMethod terminates and all local variables are destroyed leaving only b with its values unchanged by the call as shown below.
Thus a call by value does not change the value of b the parameter passed into the method.
Pass Reference By Value
Now consider the reference type version of the same code i.e. what happens when you pass a reference type by value.
In this case we need the class version of the point type, i.e. a reference type version of the object, and a suitably modified MyMethod:
As before we create an instance and set its x field to 5:
This might look the same but as the diagram shows the situation is very different. Now we have a reference variable called b and its content is a reference to a PointR object created on the heap.
Now when we call MyMethod in exactly the same way,
b is passed by value which means that a new local variable a is created and the contents of b are copied to it.
The big difference is now that the content of b is a reference to an object on the heap. The result is that we now have two reference variable referencing the object on the stack and when the assignment a.x=10 occurs in the method the object on the heap is changed as shown.
Once again when MyMethod terminates the behaviour is exactly the same. The local variables including a are destroyed but now the change made to the object on the heap persists as shown below.
You should now be able to appreciate that while both value and reference variables are passed by value the effect of making changes in the method are very different.
Also notice that in both cases you cannot make a change to the value of the paramter passed. In the value case this means you cannot change the data and in the reference case you cannot change what is referenced. That is in both cases assignment to a in the method has no effect on the variable b passed into the method.
To summarise: by default parameters are always passed by value and assignment has no effect on the variables passed in. Passing a reference type allows the method to change the fields of the object referenced.
|Last Updated ( Thursday, 19 November 2015 )|